【链表归并排序c++算法实现】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


链表归序合并

对两个升序链表进行有序合并,采用c++算法。


一、递归法

假设链表分别为 A 和 B,先比较 A 和 B 的头节点的值的大小,选择头节点值较小者(假设为 A)作为新的链表的头节点;然后再比较 A 的第二个节点的值与 B 的头节点的值的大小关系,选择较小者作为新链表的第二个节点;依次类推找出新链表的第三个节点…

1.1代码

LNode* MergeList(LNode* L1, LNode* L2)
 {
     if(L1==nullptr||L2==nullptr)
        return L1==nullptr ? L2 : L1;
    if(L1->data <= L2->data)
     {
         L1->next = MergeList2(L1->next, L2);
         return L1;
     }
     else
    {
         L2->next = MergeList2(L1,L2->next);
         return L2;
     }
 }

1.2 「复杂度分析」

时间复杂度:「O(max(m, n))」,其中 n 和 m 分别为两个链表的长度,。

空间复杂度:「O(max(m, n))」。递归调用

二、新建链表合并

2.1 代码

int MergeList(LNode* La,LNode* Lb,LNode* Lc)
216 {
217   if ( (La == nullptr) || (Lb == nullptr) || (Lc == nullptr) )
218   {
219       cout<<" 表La、Lb、Lc至少有一个不存在。\n";
220       return 0;
221   }
222   La = La->next;
223   Lb = Lb->next;
224   LNode* pp;
225   while((La!=nullptr)&&(Lb!=nullptr))
226   {
227       if(La->data<Lb->data)
228       {
229           pp = La;
230           La = La->next;
231       }
232       else
233       {
234           pp = Lb;
235           Lb = Lb->next;
236       }
237       Lc->next = new(std::nothrow)LNode;
238       Lc = Lc->next;
239       memcpy(&Lc->data,&pp->data,sizeof(ElemType));
240       Lc->next = nullptr;
241   }
242   while(La!=nullptr)
243   {
245       Lc->next = new(std::nothrow)LNode;
246       Lc = Lc->next;
247       memcpy(&Lc->data,&La->data,sizeof(ElemType));
248       Lc->next = nullptr;
249       La = La->next;
250   }
251 
252   while(Lb!=nullptr)
253   {
254       Lc->next = new(std::nothrow)LNode;
255       Lc = Lc->next;
256       memcpy(&Lc->data,&Lb->data,sizeof(ElemType));
257       Lc->next = nullptr;
258       Lb = Lb->next;
259   }
260   return 1;
261 }

2.2 「复杂度分析」

时间复杂度:「O(max(m, n))」,其中 n 和 m 分别为两个链表的长度,需要递归调用两个链表的每个节点一次。

空间复杂度:「O(n + m)」。


三、迭代法

3.1代码

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    if (l1 == nullptr || l2 == nullptr) {
        return l1 != nullptr ? l1 : l2;
    }

    ListNode* pre = nullptr;                              
    ListNode* next = nullptr;
    ListNode* mergeHead = l1->val > l2->val ? l2 : l1;  
    ListNode* cur1 = mergeHead == l1 ? l1 : l2;         
    ListNode* cur2 = mergeHead == l1 ? l2 : l1;        
    while (cur1 != nullptr && cur2 != nullptr) {
        if (cur1->val <= cur2->val) {
            pre = cur1;
            cur1 = cur1->next;
        } else {
            next = cur2->next;  
            pre->next = cur2;   
            cur2->next = cur1;  
            pre = cur2;
            cur2 = next;            
        }
    }

    pre->next = cur1 == nullptr ? cur2 : cur1;
    //cur1小于cur2的值且next为空时,pre更新为cur1最后一个节点,
    //cur1更新为空指针,循环退出,
    //此时pre没有指向下一节点,所以需要判断最后连接
    return mergeHead;
}

3.2 分析

设置两个指针 cur1 和 cur2,分别指向两个链表的头节点;
比较 cur1 和 cur2 指向的节点的值的大小,右移指向的节点值较小的 cur1;
设置一个指针 pre1,记录上次比较时值较小的节点;
设置一个指针 next,记录 cur2 指向节点的下一节点;
由于 pre1 指向的节点值小于 cur2 指向的节点值,连接它们;
同时由于 cur2 指向的节点小于 cur1 指向的节点,连接它们;
右移 pre1 和 cur2 分别到 cur2 和 next 位置;
由于 cur1 指向的节点值大于 cur2 指向的节点值,将 pre1 指向的节点连接 cur2 指向的节点;
由于 cur2 指向的节点值小于 cur1 指向的节点值,连接它们;

动图演示

3.3 「复杂度分析」

时间复杂度:「O(n + m)」,其中 n 和 m 分别为两个链表的长度,需要遍历两个链表的每个节点。

空间复杂度:「O(1)」,未开辟额外空间。

总结

采用三个方法对两个有序链表进行合并,记录一下思路。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值