分治法是解決複雜問題的經典策略,核心思想是「分而治之」:將大問題分解為若干規模較小、結構相同的子問題,遞歸求解子問題,再合併結果。快速排序正是分治法在排序領域的典型應用。
分區是快速排序的關鍵步驟,目標是選擇一個基準值,將陣列重新排列使得:
public int partitionBasic(int left, int right) {
if (left < 0 || left >= n || right < 0 || right >= n) return -1;
int pivot = arr[left]; // 選最左元素為基準
int i = left, j = right;
while (i < j) {
while (i < j && arr[j] >= pivot) j--;
if (i < j) arr[i++] = arr[j];
while (i < j && arr[i] <= pivot) i++;
if (i < j) arr[j--] = arr[i];
}
arr[i] = pivot;
return i; // 返回基準值最終位置
}
public void quickSort(int left, int right) {
if (right - left < 1) return; // 終止條件:區間長度 < 2
int pivotIndex = partitionBasic(left, right);
quickSort(left, pivotIndex - 1); // 排序左子區
quickSort(pivotIndex + 1, right); // 排序右子區
}
當陣列已有序或逆序,且每次選最左/最右元素為基準時,分區極度不平衡,退化為 O(n²)。
private int medianOfThree(int left, int right) {
int mid = (left + right) >>> 1;
// 確保 arr[left] <= arr[mid] <= arr[right]
if (arr[left] > arr[mid]) swap(left, mid);
if (arr[left] > arr[right]) swap(left, right);
if (arr[mid] > arr[right]) swap(mid, right);
// 將中位數移到 left 位置作為基準
swap(mid, left);
return arr[left];
}
private static final int INSERTION_SORT_THRESHOLD = 16;
public void quickSortOptimized(int left, int right) {
if (right - left < INSERTION_SORT_THRESHOLD) {
insertionSort(left, right);
return;
}
// ... 正常快速排序邏輯
}
public void quickSortTailRecursion(int left, int right) {
while (right - left >= INSERTION_SORT_THRESHOLD) {
int pivotIndex = partitionOptimized(left, right);
// 遞歸處理較小區間,迴圈處理較大區間(消除尾遞歸)
if (pivotIndex - left < right - pivotIndex) {
quickSortTailRecursion(left, pivotIndex - 1);
left = pivotIndex + 1;
} else {
quickSortTailRecursion(pivotIndex + 1, right);
right = pivotIndex - 1;
}
}
insertionSort(left, right);
}
初始陣列: 95 40 64 18 78 23 73 84 40
排序後: 18 23 40 40 64 73 78 84 95
| 版本 | 平均 | 最壞 | 空間 | 穩定性 |
|---|---|---|---|---|
| 基礎版 | O(n log n) | O(n²) | O(log n) | 不穩定 |
| 三數取中 | O(n log n) | O(n²)* | O(log n) | 不穩定 |
| 隨機化 | O(n log n) | O(n²)* | O(log n) | 不穩定 |
* 極低機率觸發,工程上可視為 O(n log n)
Arrays.sort()(雙軸快速排序)或 Collections.sort()(TimSort)Arrays.parallelSort()