链表练习题C++代码实现(四):将两个递增的链表合并为一个顺序递减的链表

问题:
有两个链表,都是递增的,让后将这两个链表合并成一个递减的链表。

思路:
首先我们想一想如何合并成一个递增的链表?
其实很简单,就是两个链表的每一个元素挨着比较就行了。
每次比较结束以后,将较小的结点添加到新链表里这样就可以了。
注意,这里往新节点里添加较小结点的时候要使用尾插法

那如何合并成一个递减的链表呢?
刚才我们用尾插法生成的链表是递增的。
那现在,每次插入较小结点的时候时使用头插法,最终就会得到一个递减的链表啦。
因为大的元素都会放在小元素的前面。

如何保证只使用原来两链表的存储空间呢?
用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
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辛伯达岛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值