148.排序链表

排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
在这里插入图片描述
在这里插入图片描述

提示:

链表中节点的数目在范围 [0, 5 * 10 ^4] 内
-10 ^5 <= Node.val <= 10 ^5

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

思路:链表的排序跟数组一样也有冒泡插入交换、其中O(n log n)的有快排、归并、堆排序。
堆排序和归并是O(n log n)的复杂度,这道题使用这两种都可以 过,但是快排的复杂度取决于所选的基准值、如果选第一个元素为基准值,当链表是高度有序的时候快排是O(n^2)的复杂度,所以这道题用快排需要取链表的中间元素为基准值。
代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void QuickSort(ListNode *pBegin,ListNode *pEnd){//快排的运行函数
        if(pBegin!=pEnd){//链表为空递归结束
            ListNode *slow=pBegin;//这里用两个指针一个慢,一个快,获取量表中间节点
            ListNode *fast=pBegin->next;//快指针
            while(fast!=pEnd&&fast->next!=pEnd){//快指针到pEnd或快指针的下一个节点为pEnd时结束(避免出现空指针)
                fast=fast->next->next;//快指针一次移动两格,满指针一次移动一个,快指针移动到最后时,慢指针移动到中间
                slow=slow->next;
            }
            int t=slow->val;//交换链表中间值和头节点的值
            slow->val=pBegin->val;
            pBegin->val=t;
            ListNode *mid=GetMid(pBegin,pEnd);//获取划分的节点位置
            QuickSort(pBegin,mid);//递归处理
            QuickSort(mid->next,pEnd);
        }
    }
    ListNode * GetMid(ListNode *pBegin,ListNode *pEnd){//获取结点位置函数
        ListNode *p=pBegin;
        ListNode *q=p->next;
        int t,key=pBegin->val;//存放基准值
        while(q!=pEnd){
            if(q->val<key){//如果q结点的值小于基准值
                p=p->next;//p结点先向后移动一个结点
                t=p->val;//交换p,q结点的值
                p->val=q->val;
                q->val=t;
            }
            q=q->next;//q结点移动
        }
        t=p->val;//交换p结点和pBegin结点的值
        p->val=pBegin->val;
        pBegin->val=t;
        return p;//返回pBegin结点最后位置
    }
    ListNode* sortList(ListNode* head) {//初始化,进行快排
        if(head==NULL) return head;
        ListNode *pEnd;
        ListNode *pBegin;
        pBegin=head;
        pEnd=NULL;
        QuickSort(pBegin,pEnd);
        return head;
    }
};
  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值