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

Java 經典排序算法全解析:從冒泡到歸並的核心原理與代碼實現

     編輯:Java 綜合教學

Java 經典排序算法全解析:從冒泡到歸並的核心原理與代碼實現

一、排序算法評價維度

選擇排序算法需綜合考量四大指標:

指標說明關鍵點
時間複雜度平均/最好/最壞情況O(n²) vs O(n log n)
空間複雜度額外內存消耗原地排序 O(1) vs 輔助數組 O(n)
穩定性相等元素相對順序是否保持穩定:冒泡/插入/歸並;不穩定:選擇/快排/堆排
常數因子同階複雜度下的實際速度差快排常數小於堆排,工程中常優選

二、O(n²) 簡單排序族群

1. 冒泡排序 - 優化版

核心思想:相鄰比較,大元素沉底,每輪冒泡出一個最大值

// 優化:有序標記提前終止
public static void bubbleSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        boolean sorted = true;
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);
                sorted = false;
            }
        }
        if (sorted) break; // 本輪無交換,已有序
    }
}

特點:穩定、原地、最好 O(n)、最壞 O(n²)

2. 選擇排序

核心思想:每輪在無序區選最小值,與無序區首位交換

public static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[minIdx]) minIdx = j;
        }
        if (minIdx != i) swap(arr, i, minIdx);
    }
}

特點:不穩定、原地、交換次數最少 (O(n))、無論輸入如何皆 O(n²)

3. 插入排序

核心思想:構建有序區,將新元素插入合適位置(類似整理撲克牌)

public static void insertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i], j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

特點:穩定、原地、近乎有序數據極快 O(n)、小數據量優於 O(n log n) 算法

4. 希爾排序 - 插入排序改進版

核心思想:分組插入排序,間距 d 逐漸縮小至 1,減少元素移動距離

public static void shellSort(int[] arr) {
    for (int d = arr.length / 2; d > 0; d /= 2) {
        for (int i = d; i < arr.length; i++) {
            int temp = arr[i], j = i - d;
            while (j >= 0 && arr[j] > temp) {
                arr[j + d] = arr[j];
                j -= d;
            }
            arr[j + d] = temp;
        }
    }
}

特點:不穩定、原地、時間複雜度取決於間距序列 (約 O(n^1.3~1.5))

三、O(n log n) 高效排序族群

1. 快速排序 - 實戰首選

核心思想:分治法,選基準值分區,左小右大,遞歸排序子區間

public static void quickSort(int[] arr, int low, int high) {
    if (low >= high) return;
    int i = low, j = high, pivot = arr[low];
    while (i < j) {
        while (i < j && arr[j] >= pivot) j--;
        while (i < j && arr[i] <= pivot) i++;
        swap(arr, i, j);
    }
    swap(arr, low, i); // 基準歸位
    quickSort(arr, low, i - 1);
    quickSort(arr, i + 1, high);
}

關鍵優化:隨機選基準/三數取中、小區間改插入排序、尾遞歸優化、三向切分處理大量重複元素

特點:不穩定、原地、平均 O(n log n)、最壞 O(n²)(可通過隨機化避免)

2. 歸並排序 - 穩定標杆

核心思想:分治法,遞歸拆分至單元素,歸併時有序合併

public static void mergeSort(int[] arr, int left, int right) {
    if (left >= right) return;
    int mid = (left + right) >>> 1;
    mergeSort(arr, left, mid);
    mergeSort(arr, mid + 1, right);
    merge(arr, left, mid, right);
}

private static void merge(int[] arr, int l, int m, int r) {
    int[] temp = new int[r - l + 1];
    int i = l, j = m + 1, k = 0;
    while (i <= m && j <= r) temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
    while (i <= m) temp[k++] = arr[i++];
    while (j <= r) temp[k++] = arr[j++];
    System.arraycopy(temp, 0, arr, l, temp.length);
}

特點:穩定、需 O(n) 輔助空間、鏈表上可 O(1) 空間、時間複雜度固定 O(n log n)

3. 堆排序 - 原地 O(n log n)

核心思想:構建大頂堆,反復交換堆頂與末尾元素,調整堆

public static void heapSort(int[] arr) {
    // 構建大頂堆
    for (int i = arr.length / 2 - 1; i >= 0; i--) heapify(arr, i, arr.length);
    // 依次取出堆頂
    for (int i = arr.length - 1; i > 0; i--) {
        swap(arr, 0, i);
        heapify(arr, 0, i);
    }
}

private static void heapify(int[] arr, int i, int size) {
    int largest = i;
    int left = 2 * i + 1, right = 2 * i + 2;
    if (left < size && arr[left] > arr[largest]) largest = left;
    if (right < size && arr[right] > arr[largest]) largest = right;
    if (largest != i) {
        swap(arr, i, largest);
        heapify(arr, largest, size);
    }
}

特點:不穩定、原地、時間複雜度固定 O(n log n)、常數因子較大

四、二分查找 - 有序數組的利器

public static int binarySearch(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    while (left <= right) {
        int mid = left + ((right - left) >>> 1);
        if (arr[mid] == target) return mid;
        else if (arr[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

前提:數組必須有序;複雜度:O(log n);變體:查找首次/最後一次出現位置、查找插入位置

五、算法選型決策樹

  • 小數據量 (n < 50):插入排序
  • 近乎有序:插入/希爾/冒泡優化版
  • 通用高性能:快速排序 (雙向掃描/三向切分版)
  • 要求穩定:歸並排序 (外部排序/鏈表首選)
  • 嚴格 O(n log n) 最壞情況:堆排序 / 歸並排序
  • 整數小範圍:計數/基數/桶排序 O(n)

排序算法對比表

排序算法是演算法設計的縮影,理解其分治、隨機化、空間換時間等思想,對解決複雜工程問題大有裨益。實際開發中優先使用 Arrays.sort() (雙軸快排) 或 Collections.sort() (TimSort),僅在特殊場景手寫優化。

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