链表排序算法总结

概述


问题描述:给定一个链表,请将这个链表升序排列。
  • 节点定义:
struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};

1 链表插入排序

题目描述:Leetcode 0147 链表进行插入排序

分析

  • 因为头结点可能会改变,因此需要设置一个虚拟头结点dummy

  • 我们从前向后遍历整个链表,假设当前考察节点为p,我们需要从dummy开始遍历,找到第一个大于p->val的前一个节点cur,然后将p插入到cur后面。

代码

  • C++
class Solution {public:ListNode* insertionSortList(ListNode* head) {auto dummy = new ListNode(-1);for (auto p = head; p; ) {auto cur = dummy, next = p->next;  // next是下一个需要考察的节点while (cur->next && cur->next->val <= p->val) cur = cur->next;p->next = cur->next;cur->next = p;p = next;}return dummy->next;}
};

时空复杂度分析

  • 时间复杂度:O(n2)O(n^2)O(n2),n为链表长度。

  • 空间复杂度:O(1)O(1)O(1)。

2 链表归并排序

题目描述:Leetcode 0148 排序链表

分析

  • 因为要求时间O(1),因此就不能使用递归的写法,这一题可以使用归并排序的迭代写法(自底向上)。

  • 这一题十分类似于Leetcode 0023 合并K个有序链表,我们可以使用LC23的思路求解。代码中的变量如下图所示:

  • 上面的做法用C++演示。

  • Java演示一下递归(自顶向下)的写法,但是空间复杂度不是O(1)O(1)O(1)的。关键在于找到链表的中点,与Leetcode 0109 将有序链表转换二叉搜索树类似,这两题都需要找到中点,不同于LC109,LC109的终止条件是f != null && f->next != null,这里使用的终止条件是f.next != null && f->next->next != null,两者的区别为:

  • 之后从s后截成两段,进行递归求解即可。

  • 合并两个有序链表可以使用Leetcode 0021 合并两个有序链表的方法。

代码

  • C++
class Solution {public:ListNode* sortList(ListNode* head) {int n = 0;for (auto p = head; p; p = p->next) n++;  // 求出节点数目for (int len = 1; len < n; len += len) {  // 枚举合并长度// 下面循环一次代表向上递推一层auto dummy = new ListNode(-1), cur = dummy;  // 因为头结点可能变,因此需要虚拟头结点for (int j = 1; j <= n; j += 2 * len) {  // 枚举待合并链表的起点, j不会再下面用到auto p = head, q = head;for (int i = 0; i < len && q; i++) q = q->next;auto o = q;  // o为下次合并的起点for (int i = 0; i < len && o; i++) o = o->next;// 归并p、q开头的链表int l = 0, r = 0;while (l < len && r < len && p && q)    if (p->val <= q->val) cur = cur->next = p, p = p->next, l++;else cur = cur->next = q, q = q->next, r++;while (l < len && p) cur = cur->next = p, p = p->next, l++;while (r < len && q) cur = cur->next = q, q = q->next, r++;head = o;  // 进行后面两段链表的合并}cur->next = NULL;head = dummy->next;}return head;}
};
  • Java
class Solution {public ListNode merge(ListNode l1, ListNode l2) {if (l1 == null) return l2;if (l2 == null) return l1;if (l1.val < l2.val) {l1.next = merge(l1.next, l2);return l1;} else {l2.next = merge(l1, l2.next);return l2;}}public ListNode sortList(ListNode head) {if (head == null || head.next == null) return head;// 快慢指针,寻找中间点ListNode s = head, f = head;while (f.next != null && f.next.next != null) {s = s.next; f = f.next.next;}ListNode newHead = s.next;s.next = null;  // 断开链表,分成前后两部分ListNode left = sortList(head), right = sortList(newHead);return merge(left, right);  // 返回合并后的链表头指针}
}

时空复杂度分析

  • 时间复杂度:O(n×log(n))O(n \times log(n))O(n×log(n)),n为链表长度。

  • 空间复杂度:C++: O(1)O(1)O(1)。Java:O(log(n))O(log(n))O(log(n))。

3 链表快速排序

题目描述:AcWing 1451. 单链表快速排序

分析

  • 使用三个虚拟头指针left, mid, right,记录每次partition的结果,这里取头结点val的值作为分界线。

  • 递归的过程中,我们每次都要遍历整个链表,对节点值小于val的节点接到left中,节点值等于val的节点接到mid中,节点值大于val的节点接到right中,之后还要将三个链表的尾结点置为空。

  • 接着递归处理left、right,递归结束后将三段拼接起来即可。

代码

  • C++
class Solution {public:ListNode* quickSortList(ListNode* head) {if (!head || !head->next) return head;auto left = new ListNode(-1), mid = new ListNode(-1), right = new ListNode(-1);auto ltail = left, mtail = mid, rtail = right;int val = head->val;for (auto p = head; p; p = p->next) {if (p->val < val) ltail = ltail->next = p;else if (p->val == val) mtail = mtail->next = p;else rtail = rtail->next = p;}ltail->next = mtail->next = rtail->next = NULL;left->next = quickSortList(left->next);right->next = quickSortList(right->next);// 拼接三个链表get_tail(left)->next = mid->next;get_tail(mid)->next = right->next;auto p = left->next;delete left;delete mid;delete right;return p;}// 获取链表的尾节点ListNode* get_tail(ListNode* head) {while (head->next) head = head->next;return head;}
};

时空复杂度分析

  • 时间复杂度:O(n×log(n))O(n \times log(n))O(n×log(n)),n为链表长度。

  • 空间复杂度:O(log(n))O(log(n))O(log(n))。

【算法专题】链表排序算法总结相关推荐

  1. 链表排序算法(Java实现)

    插入排序 对链表进行插入排序,是最简单的一种链表排序算法,用于插入排序是迭代的,所以每次只移动一个元素,直到所有元素可以形成一个有序的输出列表.        每次迭代中,插入排序只从输入数据中移除一 ...

  2. 数据结构之排序算法:内部排序算法的应用与比较

    排序算法:内部排序算法的应用与比较 思维导图: 比较: 应用: 思维导图: 比较: 应用:

  3. 冒泡排序算法和选择排序算法比较

      冒泡排序算法详细内容见→冒泡排序算法.   选择排序算法详细内容见→选择排序算法.   冒泡排序算法和选择排序算法的区别: 冒泡排序是比较相邻位置的两个数:而选择排序是按顺序比较,找出最大值或者最 ...

  4. 算法基础:排序算法之冒泡排序

    算法基础:排序算法之冒泡排序 实现:数列有序排序 思想:已知一个数列,令数列中相邻的两个元素一一做比较,按照小大的顺序(或从大到小的顺序),如果前一个数比后一个数大(或后一个数比前一个数大),则互换( ...

  5. java排序算法总结_排序算法总结及Java实现

    1. 整体介绍 分类 排序大的分类可以分为两种,内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.主要需要理解的都是内排序算法: 内排序可以分为 ...

  6. 归并排序执行次数_肯定能懂的常见算法讲解(1)——排序算法

    我叫水水,很高兴认识大家! 这是专栏的第七篇文章.其实本专题已经在我的公众号(公众号中不只有学习专题,还有很多大学学习资源分享.工具分享等等,文末有相关指路哦,欢迎关注撒~[微信搜索"Cod ...

  7. 用python排序算法_Python - 八大排序算法

    1.序言 本文使用Python实现了一些常用的排序方法.文章结构如下: 1.直接插入排序 2.希尔排序 3.冒泡排序 4.快速排序 5.简单选择排序 6.堆排序 7.归并排序 8.基数排序 上述所有的 ...

  8. java 排序算法总结,Java排序算法总结之归并排序

    本文实例讲述了Java排序算法总结之归并排序.分享给大家供大家参考.具体分析如下: 归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.和快速排序类似,让我们一起来看 ...

  9. 深圳大学算法实验一——排序算法性能分析

    深圳大学算法实验一 一.实验目的与要求 1. 掌握九种排序算法原理 2. 掌握不同排序算法时间效率的经验分析方法,验证理论分析与经验分析的一致性. 3. 对多种排序算法提出改进方案 4. 综合比较各种 ...

  10. 算法初探 之 排序算法

    摘<李开复:算法的力量> : 算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落.许多学生看到一些公司在招聘时要求的编程语言五花八门就产生了一种误解,认为学计算机就是学各 ...

最新文章

  1. 网络安全系列之七 网站提权
  2. 计算机国考一级系统ms,国考一级考试介绍.ppt
  3. P2596 [ZJOI2006]书架(fhq treap)
  4. 基于PyTorch+YOLOv4的口罩佩戴检测,附数据集
  5. 使用WinSCP命令上传文件到CentOS
  6. 总比特率是什么意思_新基金初始净值低于1是什么意思?什么时候开始有净值?...
  7. 机器学习算法之KNN算法,python实现
  8. 【问题解决】c.a.c.n.c.NacosPropertySourceBuilder : parse data from Nacos error,dataId:xxxxxx.yml
  9. triz矛盾矩阵_怎样利用项目TRIZ矛盾定义法,突破产品“创
  10. CQF笔记M1L5仿真和操作随机微分方程
  11. 中国重点流域已实现休禁渔制度全覆盖
  12. shoemaster安装教程(含详细图文步骤)
  13. CentOS 压缩解压
  14. 常用软件的配置与使用
  15. 我不是刘德华-新地/卢克
  16. 多元统计分析及R语言建模(第四版)-----数据,包,资源
  17. 甲乙分别自A,B两地同时相向步行,2小时后中途相遇,甲乙步行速度都提高了1千米/时,当甲到达B地后立刻按原路向A地返行,当乙到达A地后也立刻按原路向B地返行,甲乙两人在第一次相遇后3小时36分
  18. cdr文字内容显示不出来_电脑装的字体cdr里面不显示怎么办
  19. 字符串到字节数组和字节数组到字符串的转换(编码和解码问题)
  20. SEGGER J-FLASH V7.82 下载链接

热门文章

  1. c语言char sex是什么意思,2012年计算机二级C语言入门教程:结构体
  2. 【连载】第三章刚体的定轴转动第二节转动惯量 刚体定轴转动定律
  3. 一些音视频相关概念学习笔记
  4. 科学软件编辑器在科研项目中的应用感想
  5. 小行星项目第2部分测试驱动开发
  6. ReviewBoard+SVN配置强制code review
  7. python数据分析挖掘与可视化课件_python数据分析与可视化
  8. 流光快门Matlab,华为手机流光快门太好玩了!这几个特效分分钟拍出大片感
  9. windows xp 美化大师
  10. 九阵His系统总体介绍