Java 单向链表排序

1. 介绍

链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一条指向下一个节点的引用。相对于数组,链表的插入和删除操作更加高效,但是查找节点的速度相对较慢。在实际开发中,我们经常需要对链表进行排序操作,以满足特定的需求。

本文将介绍如何使用 Java 实现单向链表的排序功能。我们将首先了解链表的基本概念和特点,然后介绍常见的链表排序算法,最后通过代码示例演示如何在 Java 中实现单向链表的排序功能。

2. 链表的基本概念和特点

链表是一种动态数据结构,它的每个节点包含两个部分:数据和指向下一个节点的引用。链表的头节点是整个链表的入口点,通过头节点我们可以遍历整个链表。

链表相对于数组的主要优点是插入和删除节点的操作更加高效,因为只需要改变节点的引用指向即可,而不需要移动其他节点。然而,链表的缺点是查找节点的速度相对较慢,因为不能直接通过索引访问节点,必须从头节点开始遍历整个链表。

链表可以分为几种常见的类型,包括单向链表、双向链表和循环链表。其中,单向链表是最简单的一种链表结构,每个节点只包含一个指向下一个节点的引用。

3. 链表排序算法

链表排序是将链表中的节点按照特定的规则进行重排的过程。常见的链表排序算法包括冒泡排序、插入排序和归并排序等。

3.1 冒泡排序

冒泡排序是一种简单的排序算法,它通过多次遍历链表,比较相邻节点的值并交换位置,将较大的值逐渐“冒泡”到链表的末尾。

冒泡排序的基本思想是从链表的头节点开始,依次比较相邻节点的值,如果前一个节点的值大于后一个节点的值,则交换这两个节点的位置。重复这个过程直到链表末尾,然后再次从头节点开始,直到所有节点都排序完成。

以下是使用冒泡排序对链表进行排序的代码示例:

public class LinkedListSort {
    public ListNode bubbleSort(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        boolean swapped;
        do {
            swapped = false;
            ListNode current = head;
            while (current.next != null) {
                if (current.val > current.next.val) {
                    int temp = current.val;
                    current.val = current.next.val;
                    current.next.val = temp;
                    swapped = true;
                }
                current = current.next;
            }
        } while (swapped);

        return head;
    }
}

3.2 插入排序

插入排序是一种简单直观的排序算法,它的基本思想是将链表分为已排序部分和未排序部分,每次从未排序部分中取出一个节点,插入到已排序部分的正确位置。

插入排序的实现过程如下:

  1. 创建一个新的有序链表,初始时只包含链表的头节点。
  2. 遍历原链表,每次将一个节点插入到新链表的正确位置。
  3. 最后将新链表作为排序后的链表返回。

以下是使用插入排序对链表进行排序的代码示例:

public class LinkedListSort {
    public ListNode insertionSort(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode dummy = new ListNode(Integer.MIN_VALUE);
        ListNode current = head;
        while (current != null) {
            ListNode prev = dummy;
            while (prev.next != null && prev.next.val < current.val) {
                prev = prev.next;
            }
            
            ListNode next = current.next;
            current.next = prev.next;