《链表算法:浅谈并实现一下链表各种排序算法及其性能》

前置知识

  • 数据结构-链表
  • 数组排序算法:选择排序[解法1], 归并排序递归版[解法2],归并排序迭代法[解法3最优解]
  • [归并部分基础]合并两个有序链表
  • 如果您不满足于此, 笔者也提供冒泡排序,插入排序,快速排序的链表写法。以及,我们会在下文讨论为什么不说明希尔排序,堆排序, 因为两者不适合链表的特性。笔者不打算提供借助容器(数组)的写法, 以及衍生的3种非比较排序写法(计数排序,基数排序,桶排序的写法)其实笔者也不太了解 本篇由于时间原因, 因此鸽了部分篇幅
    本篇是对链表的排序, 笔者认为读者阅读此篇理应掌握至少一个数组的排序算法。

测试链接力扣:排序链表
测试链接力扣补充:链表的插入排序
本篇重点

  1. 熟悉选择排序的写法, 主要是讲处理数组的选择排序的思想应用于链表。主要是熟悉一下coding。
  2. 熟悉自上到底的归并排序链表写法, 采取的分治递归, 不过不是最优解,因为系统栈占据一定空间。
  3. 完全掌握迭代版本的归并排序写法。 原因: 它实现了数组不存在的排序性能。在比较排序中同时拥有时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度: O ( 1 ) O(1) O(1),还具有稳定性。 ps:数组迭代版本的快速排序是不具有稳定性的。迭代版本的归并排序的篇幅作者未更,可以自行查视频学习一下。
  4. 拓展性内容, 链表中的冒泡,插入,快速排序写法。算是数组排序算法对应应用到链表的实践吧。
    链表快速排序的内容未更...
  5. 拓展性内容, 为什么希尔排序,堆排序不适合链表? 这些排序没有对应的实现代码, 因为性能太低了没有价值。

选择排序

要求
时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1)

  • 选择排序是什么?
  • 请看VCR
// 数组中交换i和j位置的数
	public static void swap(int[] arr, int i, int j) {
   
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

	// 选择排序
	public static void selectionSort(int[] arr) {
   
		if (arr == null || arr.length < 2) {
   
			return;
		}
		for (int minIndex, i = 0; i < arr.length - 1; i++) {
   
			minIndex = i;
			for (int j = i + 1; j < arr.length; j++) {
   
				if (arr[j] < arr[minIndex]) {
   
					minIndex = j;
				}
			}
			swap(arr, i, minIndex);
		}
	}

数组版本的选择排序思想是什么?
假设数组有n个元素,只需要对前面n-1个元素排序。
[0,i-1]是已排序部分,[i,n-1]是未排序部分。每次从未排序部分选出最小值,记录最小值的下标并与i位置数组元素交换。

那么改成链表版本的怎么做?

  1. 开局初始认为排序链表是空表, 整个链表是未排序部分。
  2. 第一次,从未排序部分链表找出最小节点。将其设置新头节点(搞一个新链表)。
  3. 接下来每次从未排序部分找出最小节点,并其从原链表中删除,并且尾插到排序部分链表。
  4. 遍历完原链表都会执行上述3的操作,这个时候返回新头节点就是排序链表的下标。
class Solution {
   
    // 获取未排序链表中值最小的节点的前驱节点
    public ListNode getSmallestNode(ListNode head) {
   
        ListNode smallNode = head; // 记录当前最小节点
        ListNode smallPrev = null; // 记录当前最小节点的前驱节点
        ListNode prev = head, cur = head.next; // 初始化前驱节点和当前节点
        // 遍历链表寻找最小值
        while (cur != null) {
   
            if (cur.val < smallNode.val) {
    
                // 更新最小节点和它的前驱
                smallPrev = prev;
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值