12、在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法小区数值相同的元素,使表中不再有重复的元素。例如{7,10,10,21,30,42,42,42,51,70},将变为{7,10,21,30,42,51,70}
第一想法:遍历单链表,若当前结点的值等于其后继结点的值,则删除后继结点。否则指针后移,继续判断如此重复,直到指针为空
if(L==NULL)
return 0;
if(p->data==p->mext->data)
【】有序表,所有值域相同的结点都是相邻的。用p扫描递增单链表L,若*p结点的值域等于其后继结点的值域,则删除后者,否则p移向下一个结点。
void Del_Same(LinkList &L){
LNode *p=L->next,*q;
if(p==NULL)
return;
while(p->next!=NULL){
q=p->next;
if(p->data==q->data){
p->next=q->next;
free(q);
}
else
p=p->next;
}
}
13、假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个表的结点存放归并后的单链表。
第一想法:先看第一个元素,两个表谁的小,挨个比,用插入排序的方法实现
【】两个链表已经递增依次排序,合并时,均从第一个结点进行比较,将小的结点链入表中,同时后移工作指针。新建链表使用头插法保证元素递减排列
void MergeList(LinkList &La,LinkList &Lb){
LNode *r,*pa=La->next,*pb=Lb->next;
La->next=NULL; //La作为结果链表的头指针,先将链表初始化为空
while(pa&&pb) //两表均不空时循环
if(pa->data<=pb->data){
r=pa->next; //r暂存pa的后继结点指针
pa->next=La->next;
La->next=pa; //将pa结点链于结果表中,同时逆置(头插法)
pa=r; //恢复pa为当前待比较结点
}
else{
r=pb->next; //r暂存pb的后继结点指针
pb->next=La->next; //将pb结点链于结果表中,同时逆置(头插法)
La->next=La->next; //恢复pa为当前待比较结点
pb=r;
}
if(pa)
pb=pa;
while(pb){
r=pb->next;
pb->next;La->next;
La->next=pb;
pb=r;
}
free(Lb);
}
14.设计A和B是两个单链表(带头结点),其中元素 递增有序。设计一个算法从AB中的公共集产生单链表C。要求不破坏AB的结点
【】表A、B表都有序,可从第一个元素起依次比较A、B两表的元素,若元素值不等,则值小的指针后移,若元素值相等,则创建一个值等于两结点的元素值的新结点,使用尾插法插入到新的链表中,并将两个原表指针后移一位,直到其中一个链表遍历到表尾。
void Get_Common(LinkList A,LinkList B){
LNode *p=A->next,*q=B->next,*r,*s;
LinkList C=(LinkList)malloc(sizeof(LNode));
r=C;//r始终指向C的尾结点
while(p!=NULL&&q!=NULL){
if(p->data < q->data)
p=p->next;
else if(p->data > q->data)
q=q->next;
else{
s=(LNode*)malloc(sizeof(LNode));
s->data=p->data; //赋值产生结点*s
s->data=s; //将*s链接到C上(尾插法)
r=s;
p=p->next;
q=q->next;
}
}
r->next=NULL;
}
15、已知A、B两个单链表(带头结点),其中元素递增有序。设计一个算法求AB的交集,并存放于A中
第一想法:将AB的结点依次插入C中,每插入一个进行排序(插入排序),若遇到相等元素删除
【】采用归并思想,设置两个工作指针pa和pb,对两个链表进行归并并扫描,只有同时出现在两集合中的元素才链接到结果表中且仅保留一个,其他的结点全部释放。当一个链表遍历完毕后,释放另一个表剩下的全部结点。
LinkList Union(LinkList &la,LinkList &lb){
pa=la->next;
pb=lb->next;
pc=la;
while(pa&&pb){
pc->next=pa;
pc=pa;
pa=pa->next;
u=pb; //B中结点释放
pb=pb->next;
free(u):
}
else if(pa->data < pb->data){
u=pa;
pa=pa->next;
free(u);
}
else{
u=pb;
pb=pb->next;
free(u);
}
while(pa){
u=pa;
pa=pa->next;
free(u);
}
while(pb){
u=pb;
pb=pb->next;
free(u);
}
pc->next=NULL;
free(b);
return la;
}
}
16、两个整数序列A=a1,a2,a3,...am和B=b1,b2,b3...bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列
【】因为两个整数序列已存入两个链表中,操作从两个链表的第一个结点开始,若对应数据相等,则后移指针;若对应数据不等,则A从上次开始比较结点的后继开始,B链表仍从第一个结点开始比较,直到B链表到尾表示匹配成功。A链表到尾而B链表未到尾表示失败。
操作中应记住A链表每次开始的结点,以便下次从其后继开始
int Patern(LinkList A,LinkList B){
Lnode *p=A;
Lnode *pre=p;
Lnode *q=B;
while(p&&q){
if(p->data==q->data){
p=p->next;
q=q->next;
}
else{
pre=pre->next;
p=pre;
q=B;
}
if(q==NULL){
return 1;
else
return 0;
}
}
}
17.设计一个算法判断带头结点的循环双链表是否对称
第一想法:设立两个指针p,q,p从头开始,q从尾开始。若两指针所指结点值相同,p后移,q往前移动;若不同输出“不同”
直到p==q 结束
int Symmetry(DLinkList L){
DNode *p=L->next,*q=L->prior;
while(p!=q&&p->next!=q){
if(p->data==q->data){
p=p->next;
q=q->prior;
}
else return 0;
return 1;
}
18、有两个循环单链表。链表指针分别为h1,h2,编写一个函数将链表h2链接到h1之后,要求链接的链表仍保持循环链表形式
【】先找到两个链表的表尾指针,将第一个链表的尾指针与第二个链表的头结点链接起来,再使之成为循环的
LinkList Link(LinkList &h1,LinkList &h2){
LNode *p,*q;
p=h1;
while(p->next!=h1){
p=p->next;
q=h2;
while(q->next!=h2)
q=q->next;
p->next=h2;
q->next=h1;
return h1;
}
}
19、设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表为空
第一想法:排个序再直接输出?
【】对于循环链表,非空时循环;每循环一次查找一个最小结点(由minp指向最小值结点,minpre指向其前驱结点)并删除它。最后释放头结点。
void Del_all(LinkList &L){
LNode *p,*pre,*minp,*minpre;
while(L->next!=L){ //表不空循环
p=L->next; //p尾工作指针
pre=L; //pre指向其前驱
minp=p;
minp=p; minpre=pre;
while(p!=L){
if(p->data< minp->data)
minp=b;
}
pre=p;
p=p->next;
}
printf("%d",minp->data);
minpre->next=minp->next;
free(minp);
}
free(L);
}