问题:
有两个链表,都是递增的,让后将这两个链表合并成一个递减的链表。
思路:
首先我们想一想如何合并成一个递增的链表?
其实很简单,就是两个链表的每一个元素挨着比较就行了。
每次比较结束以后,将较小的结点添加到新链表里这样就可以了。
注意,这里往新节点里添加较小结点的时候要使用尾插法。
那如何合并成一个递减的链表呢?
刚才我们用尾插法生成的链表是递增的。
那现在,每次插入较小结点的时候时使用头插法,最终就会得到一个递减的链表啦。
因为大的元素都会放在小元素的前面。
如何保证只使用原来两链表的存储空间呢?
用A的头结点当做新表的头结点(其实用B也一样)。
在开始的时候,就让A->next=NULL。
将A的原来头结点当成一个新表的头结点就可以了。
收尾工作:
若有一个链表已经已经遍历结束,都加入新链表了,但是剩下的那个链表还剩下很多元素。
那说明剩下的元素都是比较大的,比生成的逆序链表的所有元素都大。
所以,这个时候,把剩下的元素继续使用头插法依次插入就可以了。
void MergeList(LinkList &A, LinkList &B){
//这里我们假设提供给我们的两个链表A和B都是带有头结点的
/*pa,pb分别是链表A和链表B的工作指针
*r是为暂存指针,因为若A中目前pa指向的结点添加到新表中了,那就需要一个指针提前保存好pa的下一个结点
*/
LNode *r, *pa = A->next,*pb=B->next
A->next = NUll;
while (pa && pb) {
if (pa->data <= pb->data) {
//若此时A表中工作指针指向的元素比B表中工作指针指向的元素小
//就使用头插法将这个结点保存在新表中
//注意:要先将pa->next用r保存起来,不然后面就没法继续了
r = pa->next;
pa->next = A->next;
A->next = pa;
//最后再让pa往后移动一个结点
pa = r;
}else{
//剩下的情况就是pb>pa了,流程类似
r = pb->next;
pb->next = A->next;//这里还是插入在以A为头结点的新表中
A->next = pb;
pb = r;
}
}
//若pa还有剩余
//这里是一种比较巧妙的写法,避免写大量写重复的代码,
//以为一共就两种情况,要么A有剩余,要么B有剩余,不可能都有剩余
//所以,按理说,我们应该判断下pa,如果pa不是NULL就把pa后面的结点用头插法插入
//我们还应该判断一下pb如果不是NULL就把pb后面的结点用头插法插入
//但是,这个使用pb=pa
//本质上就是,无论,pa有剩下,还是pb有剩下的,咱现在就是说,你只要有剩下
//我就把你叫做pb,然后我只对pb做处理就行了。
//这样就不用把一样的代码写两遍了
if(pa){
pb = pa;
}
//结合上一段注释理解
while (pb){
r = pb->next;
pb->next = A->next;
A->next = pb;
pb = r;
}
delete B;//最后释放B
}