(E)f1<-f1↑.link或f2=f2↑.link;
21.1)本算法功能是将双向循环链表结点的数据域按值自小到大排序,成为非递减(可能包括数据域值相等的结点)有序双向循环链表。
2)
(1)r->prior=q->prior;∥将q结点摘下,以便插入到适当位置。
(2)p->next->prior=q;∥
(2)(3)将q结点插入
(3)p->next=q;
(4)r=r->next;或r=q->next;∥后移指针,再将新结点插入到适当位置。
五、算法设计题
1.[题目分析]因为两链表已按元素值递增次序排列,将其合并时,均从第一个结点起进行比较,将小的链入链表中,同时后移链表工作指针。
该问题要求结果链表按元素值递减次序排列。
故在合并的同时,将链表结点逆置。
LinkedListUnion(LinkedListla,lb)
∥la,lb分别是带头结点的两个单链表的头指针,链表中的元素值按递增序排列,本算法将两链表合并成一个按元素值递减次序排列的单链表。
{pa=la->next;pb=lb->next;∥pa,pb分别是链表la和lb的工作指针
la->next=null;∥la作结果链表的头指针,先将结果链表初始化为空。
while(pa!
=null&&pb!
=null)∥当两链表均不为空时作
if(pa->data<=pb->data)
{r=pa->next;∥将pa的后继结点暂存于r。
pa->next=la->next;∥将pa结点链于结果表中,同时逆置。
la->next=pa;
pa=r;∥恢复pa为当前待比较结点。
}
else
{r=pb->next;∥将pb的后继结点暂存于r。
pb->next=la->next;∥将pb结点链于结果表中,同时逆置。
la->next=pb;
pb=r;∥恢复pb为当前待比较结点。
}
while(pa!
=null)∥将la表的剩余部分链入结果表,并逆置。
{r=pa->next;pa->next=la->next;la->next=pa;pa=r;}
while(pb!
=null)
{r=pb->next;pb->next=la->next;la->next=pb;pb=r;}
}∥算法Union结束。
[算法讨论]上面两链表均不为空的表达式也可简写为while(pa&&pb),两递增有序表合并成递减有序表时,上述算法是边合并边逆置。
也可先合并完,再作链表逆置。
后者不如前者优化。
算法中最后两个while语句,不可能执行两个,只能二者取一,即哪个表尚未到尾,就将其逆置到结果表中,即将剩余结点依次前插入到结果表的头结点后面。
与本题类似的其它题解答如下:
(1)[问题分析]与上题类似,不同之处在于:
一是链表无头结点,为处理方便,给加上头结点,处理结束再删除之;二是数据相同的结点,不合并到结果链表中;三是hb链表不能被破坏,即将hb的结点合并到结果链表时,要生成新结点。
LinkedListUnion(LinkedListha,hb)
∥ha和hb是两个无头结点的数据域值递增有序的单链表,本算法将hb中并不出现在ha中的数据合并到ha中,合并中不能破坏hb链表。
{LinkedListla;
la=(LinkedList)malloc(sizeof(LNode));
la->next=ha;∥申请头结点,以便操作。
pa=ha;∥pa是ha链表的工作指针
pb=hb;∥pb是hb链表的工作指针
pre=la;∥pre指向当前待合并结点的前驱。
while(pa&&pb)
if(pa->datadata)∥处理ha中数据
{pre->next=pa;pre=pa;pa=pa->next;}
elseif(pa->data>pb->data)∥处理hb中数据。
{r=(LinkedList)malloc(sizeof(LNode));∥申请空间
r->data=pb->data;pre->next=r;
pre=r;∥将新结点链入结果链表。
pb=pb->next;∥hb链表中工作指针后移。
}
else∥处理pa->data=pb->data;
{pre->next=pa;pre=pa;
pa=pa->next;∥两结点数据相等时,只将ha的数据链入。
pb=pb->next;∥不要hb的相等数据
}
if(pa!
=null)pre->next=pa;∥将两链表中剩余部分链入结果链表。
elsepre->next=pb;
free(la);∥释放头结点.ha,hb指针未被破坏。
}∥算法nion结束。
(2)本题与上面两题类似,要求结果指针为lc,其核心语句段如下:
pa=la->next;pb=hb->next;
lc=(LinkedList)malloc(sizeof(LNode));
pc=lc;∥pc是结果链表中当前结点的前驱
while(pa&&pb)
if(pa->datadata)
{pc->next=pa;pc=pa;pa=pa->next;}
else{pc->next=pb;pc=pb;pb=pb->next;}
if(pa)pc->next=pa;elsepc->next=pb;
free(la);free(lb);∥释放原来两链表的头结点。
算法时间复杂度为O(m+n),其中m和n分别为链表la和lb的长度。
2.[题目分析]本组题有6个,本质上都是链表的合并操作,合并中有各种条件。
与前组题不同的是,叙述上是用线性表代表集合,而操作则是求集合的并、交、差(A∪B,A∩B,A-B)等。
本题与上面1.
(2)基本相同,不同之处1.
(2)中链表是“非递减有序”,(可能包含相等元素),本题是元素“递增有序”(不准有相同元素)。
因此两表中合并时,如有元素值相等元素,则应删掉一个。
LinkedListUnion(LinkedListha,hb)
∥线性表A和B代表两个集合,以链式存储结构存储,元素递增有序。
ha和hb分别是其链表的头指针。
本算法求A和B的并集A∪B,仍用线性表表示,结果链表元素也是递增有序。
{pa=ha->next;pb=hb->next;∥设工作指针pa和pb。
pc=ha;∥pc为结果链表当前结点的前驱指针。
while(pa&&pb)
if(pa->datadata)
{pc->next=pa;pc=pa;pa=pa->next;}
elseif(pa->data>pb->data)
{pc->next=pb;pc=pb;pb=pb->next;}
else∥处理pa->data=pb->data.
{pc->next=pa;pc=pa;pa=pa->next;
u=pb;pb=pb->next;free(u);}
if(pa)pc->next=pa;∥若ha表未空,则链入结果表。
elsepc->next=pb;∥若hb表未空,则链入结果表。
free(hb);∥释放hb头结点
return(ha);
}∥算法Union结束。
与本题类似的其它几个题解答如下:
(1)解答完全同上2。
(2)本题是求交集,即只有同时出现在两集合中的元素才出现在结果表中。
其核心语句段如下:
pa=la->next;pb=lb->next;∥设工作指针pa和pb;
pc=la;∥结果表中当前合并结点的前驱的指针。
while(pa&&pb)
if(pa->data==pb->data)∥交集并入结果表中。
{pc->next=pa;pc=pa;pa=pa->next;
u=pb;pb=pb->next;free(u);}
elseif(pa->datadata){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){