数据结构——将两个有序链表合并(不允许开辟新的链表)

作者:小 琛
欢迎转载,请标明出处

题目:
在这里插入图片描述

题目分析

该题本身使用到的方法并没有多少难度,也就是单链表基本的插入,而在细节处理上却很容易犯错

思路讲解

首先画图(如下),绘制两个有序单链表。我们可以以一个为“基“,对”基“链表使用双指针法遍历,对另一个链表使用一个指针即可。当非“基”链表指针的当前指向值大于或等于“基”链表的第一个指针指向值且小于或等于第二个指针指向值,将此时的非“基”项使用尾插法插入,紧接着指针向前移动重复处理即可
注:我们遍历链表的时候使用双指针是因为方便插入
在这里插入图片描述
大体思路我们想到了,可链表类题目必须要考虑的点:特殊情况和边界问题,该题目一共这几个点需要考虑
1、若给的链表数据是上图,那么可以满足要求,如果数据为下图呢?
在这里插入图片描述
因此我们必须要解决:当我们选择的“基”链表的头并不是合并后的新头时的情况。
解决办法:程序进入后先处理头的问题,可令n3先指向空,n1指向“基”链表的头,若n2->date < n1->date,将n2头插,并以n3记录新头,接下来就可以继续之前思路
如图:
在这里插入图片描述

2、我们的程序必然要以指针n1和n2是否指向空为判断结束条件,假如出现n2的剩余数据比n1的最后一个数据大呢?如下图
在这里插入图片描述
此时我们并没有处理完非“基”链表,因此要加以判断:若跳出循环后,n2并不指向空,将n2及其后续链表直接尾插

3、当然还要考虑当传入的参数为空指针的情况

接下根据思路写代码:

/*
函数功能:将两个有序的链表在原地合并
入口参数:链表1头的地址、链表2头的地址
返回值:合并后链表的新头
*/
PlistNode* mergeTwoLists( PlistNode* l1,  PlistNode* l2)
{
	if (l1 == NULL)
		return l2;
	else if (l2 == NULL)
		return l1;
	PlistNode* n1 = l1;
	PlistNode* n2 = l2;
	PlistNode* n3 = NULL;
	PlistNode* cur = NULL;
	PlistNode* head = NULL;

	//处理头
	if (n1->_date >= n2->_date)
	{
		cur = n2->_next; //记录n2的下一步走向

		n3 = n2;         
		n2->_next = n1;//双指针构成

		n2 = cur;//n2向前移动
	}
	else
	{
		n3 = n1;
		n1 = n1->_next;  //构成双指针
	}
	head = n3;//新头以保存

	//双指针法进行新构建
	while ((n1 != NULL) && (n2 != NULL))
	{
		if ((n2->_date >= n3->_date) && (n2->_date <= n1->_date))
		{
			cur = n2->_next;//保存n2的下一个链

			n3->_next = n2;
			n2->_next = n1;
			n3 = n3->_next;  //双指针向前移动

			n2 = cur;//n2向前移动
		}
		else{
			n3 = n1;
			n1 = n1->_next;  //双指针向前移动
		}
	}

	//排除特殊情况
	if (n2 != NULL)
	{
		n3->_next = n2;//直接尾插即可
	}
	return head;
}

感谢浏览

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值