作者:小 琛
欢迎转载,请标明出处
题目:
题目分析
该题本身使用到的方法并没有多少难度,也就是单链表基本的插入,而在细节处理上却很容易犯错
思路讲解
首先画图(如下),绘制两个有序单链表。我们可以以一个为“基“,对”基“链表使用双指针法遍历,对另一个链表使用一个指针即可。当非“基”链表指针的当前指向值大于或等于“基”链表的第一个指针指向值且小于或等于第二个指针指向值,将此时的非“基”项使用尾插法插入,紧接着指针向前移动重复处理即可
注:我们遍历链表的时候使用双指针是因为方便插入
大体思路我们想到了,可链表类题目必须要考虑的点:特殊情况和边界问题,该题目一共这几个点需要考虑
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;
}
感谢浏览