单链表的归并排序

思路:

  相信大家对数组的归并排序非常了解,不了解的可以自己百度。本博客只是对单链表的归并排序中的小细节进行阐述.

这个图,就是一种分治的方式,当递归到最底层时,对两个数进行排序,当回到上一层,其实就得到了,两个有序的序列,然后再对这两个序列进行排序并合并成一个新的序列。这样一层一层的重复相同的操作,就可以得到整个序列的排序!

 

重点:

  对于来两个有序序列的合并,是这样合并的。

  先申请一个局部的节点(相当于 表头 ):然后,比较左右链表的最小值,谁最小就把谁拆下来,放在新的链表后面。值得注意的是:全过程只是申请了一个表头节点的内存。这一点在不计算递归所使用的内存的话,空间复杂度为O(1)

下面看图解:

      

然后,注意一下代码中p的维护,因为p是新链表的尾指针!

代码:

复制代码
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
    ListNode *sortList(ListNode *head){
        if (!head || !head->next) return head;        //空链表和只有一个元素的链表不需要排序

        ListNode *p = head, *q = head->next;
        //找到链表的中间位置
        while (q&&q->next){        //快慢指针,注意必须前两步存在
            p = p->next;
            q = q->next->next;
        }
        ListNode *left = sortList(p->next);        //右链表
        p->next = NULL;        //将其断开,为两个链表
        ListNode *right = sortList(head);
        
        return merge(left, right);
    }

    ListNode *merge(ListNode *left, ListNode *right)
    {
        ListNode dummy(0);        //申请一个假节点
        ListNode *p = &dummy;
        while (left&&right){
            if (left->val < right->val){
                p->next = left;
                left = left->next;
            }
            else{
                p->next = right;
                right = right->next;
            }
            p = p->next;
        }
        if (left)p->next = left;
        if (right)p->next = right;
        return dummy.next;
    }

};
复制代码

 

作者:ALINGMAOMAO

出处:https://www.cnblogs.com/ALINGMAOMAO/p/9884527.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   青山新雨  阅读(2410)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示