5 快速排序
5.1 原理
快速排序是一種 分治 的排序算法. 它將一個數組分成兩個子數組, 將兩部分獨立地排序.
快速排序和歸併排序是互補的:
- 歸併排序將數組分成兩個子數組分別排序, 並將有序的子數組歸併以將整個數組排序;
- 快速排序將數組排序的方式則是當兩個子數組都有序時整個數組也就自然有序了.
- 在第一種情況中, 遞歸調用發生在處理整個數組之前;
- 在第二種情況中, 遞歸調用發生在處理整個數組之後.
- 在歸併排序中, 一個數組被等分爲兩半;
- 在快速排序中, 切分 (partition) 的位置取決於數組的內容.
5.2 優點
實現簡單; 使用與各種不同的輸入數據且一般應用中比其他算法都要快得多; 原地排序( 只需要一個很小的輔助棧 ), 且將長度爲 的數組排序所需的時間和 成正比; 內循環比大多數排序算法都要短小, 這意味着它無論在理論上還是實際中都要更快.
5.3 缺點
非常脆弱, 在實現時要非常小心才能避免低劣的性能.
5.4 實現
public class Quick {
public static void sort(Comparable[] a) {
shuffle(a); //消除對輸入的依賴
sort(a, 0, a.length-1);
}
public static void sort(Comparable[] a, int lo, int hi) {
if (lo >= hi) { return; }
int j = partition(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
}
public static int partition(Comparable[] a, int lo, int hi) {
int i = lo, j = hi+1;
Comparable v = a[0];
while (true) {
while (less(a[++i], v)) { if (i==hi) { break; } }
while (less(v, a[--j])) { if (j==lo) { break; } }
if (i >= j) { break; }
exch(a, i, j);
}
exch(a, lo, j);
return j;
}
}