首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 經典排序算法實現與性能對比分析

     編輯:Java 相關知識

八大經典排序算法 Java 實現

本文整理了插入、選擇、交換、歸併、堆、希爾等六類排序的標準實現,並從時間/空間複雜度、穩定性維度進行對比,幫助選型。

代碼實現

package test;

public class SortAlgorithms {

    /** 直接插入排序 - O(n²), 穩定 */
    public void insertSort(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int temp = a[i], j = i;
            while (j > 0 && a[j - 1] > temp) {
                a[j] = a[j - 1];
                j--;
            }
            a[j] = temp;
        }
    }

    /** 折半插入排序 - 比較次數減少,移動次數不變 */
    public void binInsertSort(int[] a, int low, int high) {
        for (int i = low + 1; i <= high; i++) {
            int temp = a[i];
            int lo = low, hi = i - 1;
            while (lo <= hi) {
                int mid = (lo + hi) >>> 1;
                if (temp < a[mid]) hi = mid - 1;
                else lo = mid + 1;
            }
            for (int j = i - 1; j >= lo; j--) a[j + 1] = a[j];
            a[lo] = temp;
        }
    }

    /** 希爾排序 - 縮小增量排序 */
    public void shellSort(int[] a, int[] gaps) {
        for (int gap : gaps) {
            for (int i = gap; i < a.length; i++) {
                int temp = a[i], j = i;
                while (j >= gap && a[j - gap] > temp) {
                    a[j] = a[j - gap];
                    j -= gap;
                }
                a[j] = temp;
            }
        }
    }

    /** 簡單選擇排序 - O(n²), 不穩定 */
    public void selectSort(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < a.length; j++)
                if (a[j] < a[min]) min = j;
            if (min != i) { int t = a[i]; a[i] = a[min]; a[min] = t; }
        }
    }

    /** 堆排序 - O(n log n), 不穩定, 原地 */
    public void heapSort(int[] a) {
        int n = a.length;
        // 建堆 (從最後一個非葉子節點開始)
        for (int i = n / 2 - 1; i >= 0; i--) heapify(a, n, i);
        // 逐個提取
        for (int i = n - 1; i > 0; i--) {
            swap(a, 0, i);
            heapify(a, i, 0);
        }
    }
    private void heapify(int[] a, int n, int i) {
        int largest = i;
        int l = 2 * i + 1, r = 2 * i + 2;
        if (l < n && a[l] > a[largest]) largest = l;
        if (r < n && a[r] > a[largest]) largest = r;
        if (largest != i) { swap(a, i, largest); heapify(a, n, largest); }
    }

    /** 歸併排序 - O(n log n), 穩定, 需 O(n) 空間 */
    public void mergeSort(int[] a) {
        int[] temp = new int[a.length];
        mergeSort(a, 0, a.length - 1, temp);
    }
    private void mergeSort(int[] a, int l, int r, int[] temp) {
        if (l >= r) return;
        int m = (l + r) >>> 1;
        mergeSort(a, l, m, temp);
        mergeSort(a, m + 1, r, temp);
        merge(a, l, m, r, temp);
    }
    private void merge(int[] a, int l, int m, int r, int[] temp) {
        int i = l, j = m + 1, k = l;
        while (i <= m && j <= r) temp[k++] = (a[i] <= a[j]) ? a[i++] : a[j++];
        while (i <= m) temp[k++] = a[i++];
        while (j <= r) temp[k++] = a[j++];
        System.arraycopy(temp, l, a, l, r - l + 1);
    }

    /** 快速排序 - 平均 O(n log n), 最壞 O(n²), 不穩定 */
    public void quickSort(int[] a) {
        quickSort(a, 0, a.length - 1);
    }
    private void quickSort(int[] a, int l, int r) {
        if (l >= r) return;
        int p = partition(a, l, r);
        quickSort(a, l, p - 1);
        quickSort(a, p + 1, r);
    }
    private int partition(int[] a, int l, int r) {
        int pivot = a[r];
        int i = l - 1;
        for (int j = l; j < r; j++)
            if (a[j] <= pivot) swap(a, ++i, j);
        swap(a, i + 1, r);
        return i + 1;
    }

    private void swap(int[] a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }
}

算法性能綜合對比表

算法平均時間最壞時間最好時間空間穩定備註
插入排序O(n²)O(n²)O(n)O(1)✅小數據/近乎有序極快
折半插入O(n²)O(n²)O(n)O(1)✅減少比較,移動不變
希爾排序O(n^1.3~n²)O(n²)O(n)O(1)❌增量序列影響大
選擇排序O(n²)O(n²)O(n²)O(1)❌交換次數最少 O(n)
堆排序O(n log n)O(n log n)O(n log n)O(1)❌原地、保證性能
歸併排序O(n log n)O(n log n)O(n log n)O(n)✅穩定、外排序基礎
快速排序O(n log n)O(n²)O(n log n)O(log n)❌實際最快、隨機化避免最壞
冒泡排序O(n²)O(n²)O(n)O(1)✅教學用、優化後近乎有序快

選型決策指南

  1. 小數據量 (n < 50):插入排序、折半插入
  2. 一般通用、追求平均性能:快速排序 (雙軸/隨機化)、JDK Arrays.sort() (雙軸快排/歸併)
  3. 要求穩定排序:歸併排序、TimSort (JDK 對象排序)
  4. 嚴格保證最壞性能:堆排序、歸併排序
  5. 內存受限、原地排序:堆排序、快速排序
  6. 近乎有序數據:插入排序、冒泡排序 (優化版)
  7. 外部排序/大文件:歸併排序 (多路歸併)
  8. 並行排序:JDK 8+ Arrays.parallelSort()

JDK 內置排序實現

  • 基本類型:Arrays.sort() → 雙軸快速排序 (Dual-Pivot Quicksort)
  • 對象類型:Arrays.sort() / Collections.sort() → TimSort (歸併+插入混合),穩定
  • 並行排序:Arrays.parallelSort() → 多線程歸併/快速混合

總結

沒有「最好」的排序,只有「最合適」的排序。理解各算法的時空權衡、穩定性、數據特徵敏感度,結合實際數據規模、有序度、內存限制、穩定性要求進行選型。生產代碼優先使用 JDK 內置 Arrays.sort() / parallelSort(),特殊場景再手工實現優化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved