题目:试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为0)。
输入:不带头结点的链表个元素的值,类型为int,以9999结束。
输出:逆置单链表之后,输出单链表。
优化目标:无。
算法思想:将头结点摘下,,然后从第一个结点开始,依次插入到头结点的后面(头插法),直到最后一个结点为止,这样就实现了链表的逆置。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//逆置链表
void ReverseList(LinkList &L){
LNode *p = L->next,*s;
L->next = NULL;
while(p != NULL){
s = p->next;
p->next = L->next;
L->next = p;
p = s;
}
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
ReverseList(L);
PrintList(L);
return 0;
}
题目:有一个带头结点的单链表工,设计一个算法使其元素递增有序。
输入:不带头结点的链表个元素的值,类型为int,以9999结束。
输出:删除所有值为x的结点后输出单链表。
优化目标:无。
算法思想:算法思想:采用直接插入排序算法的思想,先构成只含一个数据结点的有序单链表,然后依次为人所扫描单链表中剩下的结点*p (直至p==NULL为止),在有序表中通过比较查找插入p的前驱结点*pre,然后将*p插入到*pre之后。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//链表排序
void Sort(LinkList &L){
LNode *p = L->next,*pre;
LNode *r = p->next;
p->next = NULL;
p = r;
while(p!=NULL){
r = p->next;
pre = L;
while(pre->next!=NULL&&pre->next->datadata){
pre = pre->next;
}
p->next = pre->next;
pre->next = p;
p = r;
}
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
Sort(L);
PrintList(L);
return 0;
}
题目:设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表
中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)。
输入:不带头结点的链表个元素的值,类型为int,以9999结束。
输出:删除所有值为x的结点后输出单链表。
优化目标:无。
算法思想:因为链表是无序的,所以只能逐个结点进行检查,执行删除前二十。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//删除介于给定值的之间的元素
void del_s_t(LinkList &L,int s,int t){
LNode *pre = L,*p = L->next,*q;
while(p!=NULL){
if(p->data>s && p->datanext;
pre->next = p;
free(q);
}
else{
pre = p;
p = p->next;
}
}
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
int s,t;
printf("请输入下界:");
scanf("%d",&s);
printf("请输入上界:");
scanf("%d",&t);
del_s_t(L,s,t);
PrintList(L);
return 0;
}
题目:給定两个单链表,编写算法找出两个链表的公共结点。
输入:不带头结点的链表个元素的值,类型为int,以9999结束。
输出:删除所有值为x的结点后输出单链表。
优化目标:无。
算法思想:*p指向的是第一个链表L1,q指向第二个链表L2,创建一个单链表L,首先对L2遍历,在每遍历L2的一个结点,然后对L1遍历看是否有相同的结点,如果有就创建新结点然后插到L中,最后返回L。(我的想法错了,题目要求是找结点相同,而不是相同元素,所以看了答案然后照着写了后面的一个)。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//查找两个链表的公共结点
LinkList similarity(LinkList L1,LinkList L2){
LinkList L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
LNode *s,*r,*p,*q;
r = L;
p = L1->next;
q = L2->next;
while(q!=NULL){
while(p!=NULL){
if(q->data == p->data){
s = (LNode *)malloc(sizeof(LNode));
s->data = q->data;
r->next = s;
s->next =NULL;
r = s;
}
p = p->next;
}
p = L1->next;
q = q->next;
}
return L;
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L1,L2,L;
creatList(L1);
PrintList(L1);
creatList(L2);
PrintList(L2);
L = similarity(L1,L2);
printf("已找到\n");
PrintList(L);
return 0;
}
算法思想:接下来我们试着去寻找一个线性时间复杂度的算法。先把问题简化:如何判断两个单向链表有没有公共结点?应注意到这样一个事实:若两个链表有一个公共结点,则该公共结点之后的所有结点都是重合的,即它们的最后一个结点必然是重合的。因此,我们判断两个链表是不是有重
合的部分时,只需要分别遍历两个链表到最后一个结点。 若两个尾结点是一样的,则说明它们有
公共结点,否则两个链表没有公共结点。然而,在上面的思路中,顺序遍历两个链表到尾结点时,并不能保证在两个链表上同时到达尾结点。这是因为两个链表长度不一定一样。但假设一个链表比另一个长 k个结点,我们先在长的链表上遍历k个结点,之后再同步遍历,此时我们就能保证同时到达最后一个结点。由于两个链表从第一个公共结点开始到链表的尾结点,这一部分是重合的,因此它们肯定也是同时到达第一公共结点的。 于是在遍历中,第一个相同的结点就是第一个公共的结点。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
int Length(LinkList L){
LNode *p = L->next;
int count = 1;
while(p!=NULL){
count++;
p = p->next;
}
return count;
}
//查找两个链表的公共结点
LinkList similarity(LinkList L1,LinkList L2){
int len1 = Length(L1),len2 = Length(L2),dist;
LinkList longList,shortList;
if(len1>len2){
longList = L1->next;
shortList = L2->next;
dist = len1-len2;
}
else{
longList = L2->next;
shortList = L1->next;
dist = len2-len1;
}
while(dist--){
longList = longList->next;
}
while(longList!=NULL){
if(longList == shortList){
return longList;
}
else{
longList = longList->next;
shortList = shortList->next;
}
}
return NULL;
}
//创建链表
void creatList(LinkList &L1,LinkList &L2){
LNode *s,*r,*p;
int x;
L1 = (LinkList)malloc(sizeof(LNode));
L2 = (LinkList)malloc(sizeof(LNode));
L1->next = NULL;
r = L1;
L2->next = NULL;
p = L2;
s = (LNode *)malloc(sizeof(LNode));
s->data = 3;
r->next = s;
s->next = NULL;
r = s;
s = (LNode *)malloc(sizeof(LNode));
s->data = 4;
p->next = s;
s->next = NULL;
p = s;
p->next = r;
// s = (LNode *)malloc(sizeof(LNode));
// s->data = 5;
// p->next = s;
// r->next = s;
// s->next = NULL;
// p = s;
// r = s;
printf("请输入链表元素值(以9999结束):");
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L1,L2,L;
creatList(L1,L2);
PrintList(L1);
PrintList(L2);
L = similarity(L1,L2);
printf("已找到\n");
PrintList(L);
return 0;
}
今日总结:做了几个单链表的题,还是感觉不错的,我觉得需要好好加强对单链表的代码练习,还要多做多练。明天继续。