链表的排序

Posted  落禅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表的排序相关的知识,希望对你有一定的参考价值。

148. 排序链表

你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:

你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例 1:

输入:head = [4,2,1,3]
输出:[1,2,3,4]

示例 2:

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例 3:

输入:head = []
输出:[]

链表排序的最佳方法:归并排序

1.找到中间节点

2.将中间节点断成左右两半,然后再次递归找到中间节点,再次进行分割,直到最后分割成一个一个的单个元素

3.然后两两排序,之后四四排序…直到最后将整张链表排成一个有序链表

这个思想和归并排序一样,归并排序的原理也是将数据分割成小部分,然后每一个小部分进行排序,让局部有序,然后整体有序

class Solution {
public:
//链表的排序:归并排序
//1.找到中间节点
//2.将链表分为两部分
//3.实现有序链表的排序
    ListNode*Sort(ListNode*&l,ListNode*&r)
    {
    //到这里就是排序的思想了,排序思想和合并两个有序链表的思想差不多
    //创建新的节点,然后按照插入排序的思想,谁大谁就插入
    //如果这边有点问题的话可以去看看合并两个有序链表
        ListNode*dummyHead=new ListNode(0);
        ListNode*cur=dummyHead;
        while(l!=nullptr&&r!=nullptr)
        {
            if(l->val<=r->val)
            {
                cur->next=l;
                cur=cur->next;
                l=l->next;
            }
            else
            {
                cur->next=r;
                cur=cur->next;
                r=r->next;
            }
        }
        if(l!=nullptr)
        {
            cur->next=l;
        }
        if(r!=nullptr)
        {
            cur->next=r;
        }
        return dummyHead->next;
    }
    //传递参数时记得引用传递
    ListNode*MergSort(ListNode*&head)
    {
    //判断头节点的下一个节点是否为空,如果是,直接返回头节点
        if(head->next==nullptr)
        return head;
        //定义快慢指针,寻找中间节点
        ListNode*slow=head;
        ListNode*fast=head;
        ListNode*prev=nullptr;
        while(fast&&fast->next)
        {
            prev=slow;
            slow=slow->next;
            fast=fast->next->next;
        }
        //此时slow所在的位置就是中间节点所在的位置,prev指向slow的前一个节点
        //我们人为的让链表从slow这个地方断开,head->prev是链表的前半段,slow到完是链表的右半部分
        prev->next=nullptr;
		//递归在左、右两端继续找中间节点
        ListNode*l=MergSort(head);
        ListNode*r=MergSort(slow);
        //当分割的不能分割时,进行排序,最开始两两排序,到后来四四排序
        return Sort(l,r);
    }
    ListNode* sortList(ListNode* head) {
    //1.判断节点是否为空
        if(head==nullptr)
        return head;
        //2.进入归并排序,寻找中间节点
        return MergSort(head);

    }
};

以上是关于链表的排序的主要内容,如果未能解决你的问题,请参考以下文章

代码模板实现双向链表的去重拼接合并排序

(链表)链表的排序问题

链表的快速排序问题

链表的排序(归并排序+快慢指针)

在编写合并两个排序链表的代码时获取地址错误的运行时负载

创建链表的同时自动完成结点数据排序