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

深度解析快速排序分區策略:挖坑填數法與雙指針法 Java 完整實現

     編輯:Java 相關知識

快速排序核心思想回顧

快速排序由 C.A.R. Hoare 1962 年提出,屬於分治法典型應用。核心三步走:

  1. 選取基準值
  2. 分區:將小於基準值的元素移到左側,大於等於的移到右側
  3. 遞迴處理左右子區間,直到區間長度為 1

分區過程中邊界處理最易出錯,本文深度剖析兩種經典分區寫法。

方法一:挖坑填數法

核心邏輯:將基準值「挖出」形成坑位,右指針找小於基準值的填左坑,左指針找大於基準值的填右坑,交替進行直到指針相遇,最後將基準值填入最終坑位。

完整可執行 Java 實現

public class QuickSortPit {
    /** 單次分區,返回基準值最終位置 */
    static int partition(int[] arr, int left, int right) {
        int pivot = arr[left]; // 選最左為基準
        int l = left, r = right;
        
        while (l < r) {
            // 1. 從右向左找 < pivot
            while (l < r && arr[r] >= pivot) r--;
            if (l < r) arr[l++] = arr[r]; // 填左坑,左指針右移
            
            // 2. 從左向右找 > pivot
            while (l < r && arr[l] <= pivot) l++;
            if (l < r) arr[r--] = arr[l]; // 填右坑,右指針左移
        }
        arr[l] = pivot; // 基準值歸位
        return l;
    }
    
    static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            int pivotIdx = partition(arr, left, right);
            quickSort(arr, left, pivotIdx - 1);
            quickSort(arr, pivotIdx + 1, right);
        }
    }
    
    public static void main(String[] args) {
        int[] data = {72, 6, 57, 88, 60, 42, 83, 73, 48, 85};
        System.out.println("原始:" + Arrays.toString(data));
        quickSort(data, 0, data.length - 1);
        System.out.println("排序:" + Arrays.toString(data));
    }
}

執行流程圖解(以 72 為基準)

初始: [72, 6, 57, 88, 60, 42, 83, 73, 48, 85]  坑位=0(72)
右找48<72 → 填坑0: [48, 6, 57, 88, 60, 42, 83, 73, 48, 85]  新坑位=8
左找88>72 → 填坑8: [48, 6, 57, 88, 60, 42, 83, 73, 88, 85]  新坑位=3
右找60<72 → 填坑3: [48, 6, 57, 60, 60, 42, 83, 73, 88, 85]  新坑位=4
左找83>72 → 填坑4: [48, 6, 57, 60, 83, 42, 83, 73, 88, 85]  新坑位=5
右找42<72 → 填坑5: [48, 6, 57, 60, 83, 42, 83, 73, 88, 85]  新坑位=5
指針相遇於5 → 填入基準值72: [48, 6, 57, 60, 83, 72, 83, 73, 88, 85]
左側全<72,右側全>72,分區完成

方法二:雙指針交換法

核心邏輯:左指針 low 從左向右找 > pivot,右指針 high 從右向左找 < pivot,兩指針未交錯時交換元素,最後將基準值與 high 位置交換。

精簡實現

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

兩種寫法深度對比

維度挖坑填數法雙指針交換法
賦值次數每次移動 1 次賦值每次交換 3 次賦值
程式碼直觀度邏輯連貫,易理解經典教科書寫法,通用性強
邊界條件處理需注意 l 與 l==r需注意 low<=high 循環條件
適用場景元素移動成本高(大對象)通用場景,標準庫多採用

優化建議(生產環境必看)

  • 三數取中法選基準:mid = (left+right)/2,取 arr[left]、arr[mid]、arr[right] 中位數,避免有序陣列退化 O(n²)
  • 小區間插入排序:區間長度 < 10-15 時改用插入排序,減少遞迴開銷
  • 尾遞迴優化:對較大分區遞迴,較小分區迭代,防止棧溢出
  • 隨機化基準:swap(arr, left, random(left, right)),期望時間複雜度穩定 O(n log n)

總結

「挖坑填數」邏輯更貼近分區本質,賦值次數少,適合大對象排序;「雙指針交換」是教科書標準寫法,通用性強。掌握兩者邊界細節,並結合三數取中、小區間插入排序等優化,即可寫出生產級快速排序。建議動手在紙上模擬 5-6 個元素的分區過程,深度內化指針移動邏輯。

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