分析过程:
首先我要合并有序的链表,合并后依然有序。我就要有两个指针,分别指向两个链表,观察所给的两个链表是升序还是降序的来确定合并后的链表是否有序。(这里默认的认为链表时升序的)
用指针分别指向两个链表的第一个节点,比较大小,那个大,将元素尾插进入我所要返回的新链表中去。一次比较循环往复,直至某一个链表为空为止。但有可能会出现一个链表为空,另一个链表不为空。我们就要在最后检测,将不为空链表的全部挂在我要返回元素的后面。因为要不停的给新链表尾插。所以我用一个指针,将新链表的尾部标记。
代码如下所示
//合并两个有序链表,合并后依然有序的测试
SLinkList* MergeLinkList(SLinkList* pHead1, SLinkList* pHead2)
{
SLinkList* New = NULL;//合并后的链表
SLinkList* tail = NULL;//标记合并后链表的尾部,方便尾插
SLinkList* cur1 = pHead1;
SLinkList* cur2 = pHead2;
SLinkList* nxt = NULL;//用来保存链表的后续节点
while (cur1 != NULL && cur2 != NULL)
{
if (cur1->_data <= cur2->_data)
{
nxt = cur1->_pNext;//保存cur1后面的节点
//应取链表1的结点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
if (New == NULL)
{ //合并的链表为空
New = cur1;//将cur1指向的结点挂在新链表上
}
else
{ //合并链表不为空
tail->_pNext = cur1;
}
cur1->_pNext = NULL;//尾插,链表的最后一个元素应为空
//保存新链表的最后一个节点
tail = cur1;
cur1 = nxt;
}
else
{
nxt = cur2->_pNext;//保存cur1后面的节点
//应取链表1的结点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
if (New == NULL)
{ //合并的链表为空
New = cur2;//将cur1指向的结点挂在新链表上
}
else
{ //合并链表不为空
tail->_pNext = cur2;
}
cur2->_pNext = NULL;//尾插,链表的最后一个元素应为空
//保存新链表的最后一个节点
tail = cur2;
cur2 = nxt;
}
}
//一个链表空了,但要判断里另一个链表为不为空
if (cur1 == NULL)
{
tail->_pNext = cur2;
}
if (cur2 == NULL)
{
tail->_pNext = cur1;
}
return New;
}
由于这个代码有许多重复的步骤,优化可得
SLinkList* MergeLinkListOP(SLinkList* pHead1, SLinkList* pHead2)
{
SLinkList* New = NULL;//合并后的链表
SLinkList* tail = NULL;//标记合并后链表的尾部,方便尾插
SLinkList* cur1 = pHead1;
SLinkList* cur2 = pHead2;
SLinkList* nxt = NULL;//用来保存链表的后续节点
SLinkList* node = NULL;
while (cur1 != NULL && cur2 != NULL)
{
if (cur1->_data <= cur2->_data)
{
node = cur1;//应取链表1的结点
}
else
{
node = cur2;
}
//保存cur1后面的节点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
nxt = node->_pNext;
if (New == NULL)
{ //合并的链表为空
New = node;//将cur1指向的结点挂在新链表上
}
else
{ //合并链表不为空
tail->_pNext = node;
}
node->_pNext = NULL;//尾插,链表的最后一个元素应为空
//保存新链表的最后一个节点
tail = node;
//已经将节点挂在新链表上,循环应该让cur1 和 cur2如改变,因此在这里应该让cur前进
if (node == cur1)
{
cur1 = nxt;
}
else
{
cur2 = nxt;
}
}
//一个链表空了,但要判断里另一个链表为不为空
if (cur1 == NULL)
tail->_pNext = cur2;
if (cur2 == NULL)
tail->_pNext = cur1;
return New;
}
链表结构、测试代码、运行结果
typedef int DataType;
typedef struct ListNode
{
DataType _data; //当前节点中所保存的元素
struct ListNode* _pNext; //指向链表中下一个结点
}SLinkList, SListNode;
void Test_MergeLinkList()
{
SLinkList* pHead1 = NULL;
SLinkList* pHead2 = NULL;
PushBack(&pHead1, 2);
PushBack(&pHead1, 4);
PushBack(&pHead1, 5);
PushBack(&pHead1, 7);
PushBack(&pHead2, 1);
PushBack(&pHead2, 3);
PushBack(&pHead2, 5);
PushBack(&pHead2, 6);
printf("链表1:");
PrintSLinkList(pHead1);
printf("链表2:");
PrintSLinkList(pHead2);
SLinkList* pHead3 = MergeLinkList(pHead1, pHead2);
printf("新链表:");
PrintSLinkList(pHead3);
SLinkList* pHead3OP = MergeLinkListOP(pHead1, pHead2);
printf("优化后的新链表:");
PrintSLinkList(pHead3);
}