IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【算法】链表的快速排序和归并排序 -> 正文阅读

[数据结构与算法]【算法】链表的快速排序和归并排序

1. 概述

我们在讨论快速排序和归并排序的时候通常是针对数组来进行讨论的,常见的的算法教科书和文档也几乎都是讨论的数组。

快速排序和归并排序对链表是同样的。只要把其思想应用于链表。

?

2. 链表的快速排序

算法步骤

快速排序的思想就是每次选出一个作为划分点,在这个划分点的左边全部是比这个划分点小的,在右边全部是比这个划分点大的。只是在链表的快速排序中,这个划分点是一个结点,而在数组的快速排序中,这个划分点是一个数。

1.pivot选择为链表的第一个结点,small指向比pivot结点值小的最后一个结点,cur指针遍历整个链表。

当cur的值比pivot的值小的话,就将cur结点的值与small的下一个结点交换。这样到最后small结点及之前的结点都是比pivot值小的,small结点之后的都是比pivot值大的;

private ListNode partition(ListNode head, ListNode tail) {
    // mark head node as the pivot node
    int pivot = head.val;
    ListNode small = head, cur = head;
    while (cur != tail) {
        if (cur.val < pivot) {
            small = small.next;
            // swap small node's value with cur node's val
            int tmp = small.val;
            small.val = cur.val;
            cur.val = tmp;
        }
        cur = cur.next;
    }
    // swap pivot node's value with last small node's value
    head.val = small.val;
    small.val = pivot;
    // return the last small node as the pivot node
    return small;
}

2.然后再将pivot结点归位,即pivot的值与small最后一个交换,那么pivot归到了本属于它的位置。

3.然后,根据快速排序的 Divide and Conquer 思想再对前半部分和后半部分分别进行排序。

public ListNode quickSortLinkedList(ListNode head) {
    if (head == null || head.next == null) return head;
    return quickSort(head, null);
}

private ListNode quickSort(ListNode head, ListNode tail) {
    if (head == tail) return head;
    ListNode mid = partition(head, tail);
    quickSort(head, mid);
    quickSort(mid.next, tail);
    return head;
}

?

测试

package cn.pku.edu.algorithm.leetcode.plus;

import cn.pku.edu.algorithm.leetcode.common.ListNode;

/**
 * @author allen
 * @date 2022/10/11
 */
public class LinkedListQuickSort {

    public ListNode quickSortLinkedList(ListNode head) {
        if (head == null || head.next == null) return head;
        return quickSort(head, null);
    }

    private ListNode quickSort(ListNode head, ListNode tail) {
        if (head == tail) return head;
        ListNode mid = partition(head, tail);
        quickSort(head, mid);
        quickSort(mid.next, tail);
        return head;
    }

    private ListNode partition(ListNode head, ListNode tail) {
        // mark head node as the pivot node
        int pivot = head.val;
        ListNode small = head, cur = head;
        while (cur != tail) {
            if (cur.val < pivot) {
                small = small.next;
                // swap small node's value with cur node's val
                int tmp = small.val;
                small.val = cur.val;
                cur.val = tmp;
            }
            cur = cur.next;
        }
        // swap pivot node's value with last small node's value
        head.val = small.val;
        small.val = pivot;
        // return the last small node as the pivot node
        return small;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(4);
        ListNode listNode2 = new ListNode(1);
        ListNode listNode3 = new ListNode(2);
        ListNode listNode4 = new ListNode(7);
        ListNode listNode5 = new ListNode(6);
        ListNode listNode6 = new ListNode(3);
        ListNode listNode7 = new ListNode(5);

        head.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;
        listNode4.next = listNode5;
        listNode5.next = listNode6;
        listNode6.next = listNode7;

        ListNode.printList(head);
        LinkedListQuickSort linkedListQuickSort = new LinkedListQuickSort();
        ListNode res = linkedListQuickSort.quickSortLinkedList(head);
        ListNode.printList(res);
    }
}

?

3. 链表的归并排序

算法步骤

链表的归并排序跟快速排序虽有一些区别的,但是都是采用的 Divide and Conquer 思想来处理问题的,它每次将一个链表拆分成两段,对两段分别再归并排序,完成后再将merge两个有序的子链表。

1.将原链表拆分成左右两段,通过快慢指针找出链表的中间位置断开为两个子链表;

2.再分别对左右两个子链表采用归并排序;即会递归地调用归并排序,直到子链表为空或者子链表中只有一个结点,就可以直接返回链表本身,因为它已经是有序的了;

public ListNode mergeSort(ListNode head) {
    if (head == null || head.next == null) return head;
    // 1. 拆分链表为左右两个子链表
    ListNode fast = head, slow = head;
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    fast = slow.next;
    slow.next = null;
    // 2. 对左右子链表分别递归地进行归并排序,使得两个子链表是有序的
    ListNode left = mergeSort(head);
    ListNode right = mergeSort(fast);
    // 3. 对两个有序的子链表进行merge,得到整体有序的链表
    return mergeTwoLists(left, right);
}

3.对得到的两个有序的子链表采用merge操作,使得整个链表成为有序链表;

private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
    ListNode dummy = new ListNode(-1), pre = dummy;
    while (list1 != null && list2 != null) {
        if (list1.val <= list2.val) {
            pre.next = list1;
            list1 = list1.next;
        } else {
            pre.next = list2;
            list2 = list2.next;
        }
        pre = pre.next;
    }
    if (list1 != null) pre.next = list1;
    if (list2 != null) pre.next = list2;
    return dummy.next;
}

?

测试

package cn.pku.edu.algorithm.leetcode.plus;

import cn.pku.edu.algorithm.leetcode.common.ListNode;

/**
 * @author allen
 * @date 2022/10/11
 */
public class LinkedListMergeSort {

    public ListNode mergeSort(ListNode head) {
        if (head == null || head.next == null) return head;
        // 1. 拆分链表为左右两个子链表
        ListNode fast = head, slow = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        fast = slow.next;
        slow.next = null;
        // 2. 对左右子链表分别递归地进行归并排序,使得两个子链表是有序的
        ListNode left = mergeSort(head);
        ListNode right = mergeSort(fast);
        // 3. 对两个有序的子链表进行merge,得到整体有序的链表
        return mergeTwoLists(left, right);
    }

    private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode(-1), pre = dummy;
        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                pre.next = list1;
                list1 = list1.next;
            } else {
                pre.next = list2;
                list2 = list2.next;
            }
            pre = pre.next;
        }
        if (list1 != null) pre.next = list1;
        if (list2 != null) pre.next = list2;
        return dummy.next;
    }

    /**
     * 测试
     */
    public static void main(String[] args) {
        ListNode head = new ListNode(4);
        ListNode listNode2 = new ListNode(1);
        ListNode listNode3 = new ListNode(2);
        ListNode listNode4 = new ListNode(7);
        ListNode listNode5 = new ListNode(6);
        ListNode listNode6 = new ListNode(3);
        ListNode listNode7 = new ListNode(5);

        head.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;
        listNode4.next = listNode5;
        listNode5.next = listNode6;
        listNode6.next = listNode7;

        ListNode.printList(head);
        LinkedListMergeSort mergeSort = new LinkedListMergeSort();
        ListNode res = mergeSort.mergeSort(head);
        ListNode.printList(res);
    }
}

?

参考文献

[1] https://blog.csdn.net/yueguangmuyu/article/details/119102492
[2] https://iq.opengenus.org/quick-sort-on-linked-list/

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:59:49  更:2022-10-17 13:02:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 1:59:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计