一、基本的快速排序
在數組中選取一個元素為基點,然后想辦法把這個基點元素移動到它在排好序后的最終位置,使得新數組中在這個基點之前的元素都小於這個基點,而之后的元素都大於這個基點,然后再對前后兩部分數組快速排序,直到數組排序完成。
代碼實現:
public void quickSorted ( int arr[] ) { int n = arr.length - 1; // 閉區間 [0...n] __quickSorted (arr, 0, n); } private __quickSorted( int arr[], int L, int R) { if ( (L >= R) { return; } // 將基點移動到最終位置的方法 int p = __partioner(arr, L, R); // 遞歸拆分數組 __quickSorted(arr, L, p - 1); __quickSorted(arr, p + 1, R); }
那么最大的問題就是怎么把這個基點移動到它最終應該所在的位置。
代碼實現:
private int __partioner ( int arr[], int L, int R ) { int v = arr[L]; // [L + 1, j] < v ; [j + 1, i) > v; int j = L; for ( int i = L + 1; i <= R; i++ ) { if ( arr[i] < v) { // 交換 arr[i] 和 arr [j + 1] int tmp = arr[j + 1]; arr[j + 1] = arr[i]; arr[i] = tmp; j++; } } // 交換 arr[j] 和arr[L] int tmp = arr[j]; arr[j] = arr[L]; arr[L] = tmp; return j; }
最終實現:

public void quickSorted ( int arr[] ) { int n = arr.length - 1; // 閉區間 [0...n] __quickSorted (arr, 0, n); } private __quickSorted( int arr[], int L, int R) { if ( (L >= R) { return; } // 將基點移動到最終位置的方法 int p = __partioner(arr, L, R); // 遞歸拆分數組 __quickSorted(arr, L, p - 1); __quickSorted(arr, p + 1, R); } private int __partioner ( int arr[], int L, int R ) { int v = arr[L]; // [L + 1, j] < v ; [j + 1, i) > v; int j = L; for ( int i = L + 1; i <= R; i++ ) { if ( arr[i] < v) { // 交換 arr[i] 和 arr [j + 1] int tmp = arr[j + 1]; arr[j + 1] = arr[i]; arr[i] = tmp; j++; } } // 交換 arr[j] 和arr[L] int tmp = arr[j]; arr[j] = arr[L]; arr[L] = tmp; return j; }
二、快速排序的優化
1. 快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序
private __quickSorted( int arr[], int L, int R) { // if ( (L >= R) { // return; // } // 快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序 if ( R - L <= 15) { insertSorted(arr, L, R); return; } // 將基點移動到最終位置的方法 int p = __partioner(arr, L, R); // 遞歸拆分數組 __quickSorted(arr, L, p - 1); __quickSorted(arr, p + 1, R); } // 減小遞歸的深度轉而使用選擇排序 private void insertSorted(int arr[], int L, int R) { for (int i = L + 1; i <= R; i++) { int i = arr[i]; int j; for (j = i; j > L && arr[j - 1] > e; j--) { arr[j] = arr[j - 1]; } } return; }
2. 優化二,基點的選擇隨機化
private int __partioner ( int arr[], int L, int R ) { // 第二次優化,將基點的選擇隨機化 int rand = (new Random().nextInt(R + 1)) + L; // 交換最左側和隨機點的元素 int tmp = arr[rand]; arr[rand] = arr[L]; arr[L] = tmp; int v = arr[L]; // [L + 1, j] < v ; [j + 1, i) > v; int j = L; for ( int i = L + 1; i <= R; i++ ) { if ( arr[i] < v) { // 交換 arr[i] 和 arr [j + 1] int tmp = arr[j + 1]; arr[j + 1] = arr[i]; arr[i] = tmp; j++; } } // 交換 arr[j] 和arr[L] int tmp = arr[j]; arr[j] = arr[L]; arr[L] = tmp; return j; }
三、兩路快排
解決排序的數組中存在多數重復元素的情況
代碼實現

public void quickSorted ( int arr[] ) { int n = arr.length - 1; // 閉區間 [0...n] __quickSorted (arr, 0, n); } private __quickSorted( int arr[], int L, int R) { // if ( (L >= R) { // return; // } // 快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序 if ( R - L <= 15) { insertSorted(arr, L, R); return; } // 將基點移動到最終位置的方法 int p = __partioner(arr, L, R); // 遞歸拆分數組 __quickSorted(arr, L, p - 1); __quickSorted(arr, p + 1, R); } private int __partioner ( int arr[], int L, int R ) { // 第二次優化,將基點的選擇隨機化 int rand = (new Random().nextInt(R + 1)) + L; // 交換最左側和隨機點的元素 int tmp = arr[rand]; arr[rand] = arr[L]; arr[L] = tmp; int v = arr[L]; // 兩路快排的實現過程 int i = L + 1; int j = R ; while (true) { while (i <= R && arr[i] < v ){ i++; } while (j >= L + 1 && arr[j] > v) { j--; } if (i > j) { break; } // 交換 i 和 j 的位置 int tmp arr[i]; arr[i] = arr[j]; arr[j] = tmp; } int tmp arr[L]; arr[L] = arr[j]; arr[j] = tmp; return j; } // 減小遞歸的深度轉而使用選擇排序 private void insertSorted(int arr[], int L, int R) { for (int i = L + 1; i <= R; i++) { int i = arr[i]; int j; for (j = i; j > L && arr[j - 1] > e; j--) { arr[j] = arr[j - 1]; } } return; }
四、三路快排
代碼實現:

public static void quickSorted3Ways(int arr[]) { int n = arr.length -1; // arr[0, n] 閉區間 __quickSorted3Ways(arr, 0, n); } private static void __quickSorted3Ways(int[] arr, int L, int R) { // if (L >= R) { // return; // } // 快速排序的第一次優化,減小遞歸的深度,轉而使用 選擇排序 if ( R - L <= 15) { insertSorted(arr, L, R); return; } // 第二次優化,將基點的選擇隨機化 int rand = (new Random().nextInt(R + 1)) + L; // 交換最左側和隨機點的元素 int tmp = arr[rand]; arr[rand] = arr[L]; arr[L] = tmp; int v = arr[L]; // partioner // 這三個變量的初始值 , 相當重要 int lt = L; // arr[L + 1, lt] < v int gt = R + 1; // arr[gt, R] > v int i =L + 1; // arr[lt + 1, i ) ==v // 此處的 i 的比較對象 while (i < gt ) { if (arr[i] < v) { SortedHandler.swap(arr, i, lt + 1); lt++; i++; } else if (arr[i] > v) { SortedHandler.swap(arr, i, gt - 1); gt--; } else { i++; } } SortedHandler.swap(arr, lt, L); __quickSorted3Ways(arr, L, lt -1); __quickSorted3Ways(arr, gt, R); }
最后附上整篇 關於快速排序從實現到逐步優化的思路圖 (畫到我懷疑人生了....)