排序单向链表

使用快速排序算法,对单向链表排序

题目:
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4

示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5
// 快速排序,需要借助轴点
// 所谓轴点(pivot):其左侧元素均不比它大,其右侧元素均不比它小

/*
 template <typename T>
 void quickSort(int lo, int hi)
 {
	 if (hi - lo < 2) return;	// 单元素区间自然有序,否则
	 int mi = partition(lo, hi - 1); // 先构造轴点
	 quickSort(lo, mi);
	 quickSort(mi + 1, hi);
 }
*/

// 快速排序的核心就是如何快速确定轴点
// 在有序序列中,所有元素皆为轴点;反之亦然
// 所以所谓快速排序,就是将所有元素逐个转换为轴点的过程
// 可以通过适当的交换,可使任一元素转换为轴点

/*

  普通的快速排序,是将序列划分成:候选轴点、所有元素不大于候选轴点的子序列L,未知大小序列U,所有元素不小于候选轴点的子序列G
  |lo|     L     |      U     |     G     |
   ↑             ↑      ↑     ↑
   0            lo      k     hi
   参数说明:秩为0处是候选轴点,lo为子序列L与U的分界,hi为子序列G与U的分界,hi与lo碰面位置即为候选轴点存放位置

  快速排序的一个变种即,讲序列划分成:候选轴点、所有元素不大于候选轴点的子序列L,所有元素不小于候选轴点的子序列G,未知大小序列U
  |lo|     L     |      G     |     U     |
   ↑             ↑            ↑
   0             mi           k
   参数说明:秩为0处是候选轴点,mi为子序列L与G的分界,k为子序列G与U的分界,最终mi停止的位置,即为候选轴点存放位置
   [k]不小于轴点 ? 直接拓展G(即k++) : G滚动后移,L拓展(即++mi),且交换mi与k,k++
*/

// 快速排序的变种,正好满足单向链表,寻秩只能从起到末的访问特点
// 对于链表,节点交换的惯性思维是,指针交换,其实可以直接将链表的两节点的值交换来完成换位操作 

#include <vector> 
using namespace std;

struct ListNode {
	 int val;
	 ListNode *next;
	 ListNode(int x) : val(x), next(nullptr) {}
 };

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		sortList(head, nullptr);
		return;
	}

	void sortList(ListNode* lo, ListNode* hi)
	{
		if (lo == hi)			// 递归基,递归结束条件,即当待排序链表只有一个节点时
			return;

		ListNode* mi = paitition(lo, hi);
		sortList(lo, mi);
		sortList(mi->next, hi);
	}

	ListNode* paitition(ListNode* lo, ListNode* hi)
	{
		ListNode* pivot = lo;		// 候选轴点
		ListNode* mi = lo;			// 序列L与G的分界点,指向L序列的最后一个
		for (ListNode* k = lo->next; k != hi; k = k->next)		// 子序列G与U的分界,直到k遍历到整个链表的最末节点结束
		{
			if (k->val < pivot->val)
			{
				mi = mi->next;		// k比pivot小,所以k此时的位置应属于L序列,将mi后一个元素与k的值交换,可以起到将L序列扩大
				swap(mi, k);
			}
		}
		// 此时,mi所在节点即为轴点应存放位置
		swap(pivot, mi);
		return mi;
	}

	void swap(ListNode* a, ListNode* b)
	{
		int val = a->val;
		a->val = b->val;
		b->val = val;
	}
};

复杂度分析:

时间复杂度:快速排序的平均时间复杂度为O(n*(log\;n)),最坏时间复杂度为O(n^{2}),对于此题也不例外

空间复杂度:没有将链表在额外空间上操作,只申请了几个中间变量,空间复杂度为O(n)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值