快排概念
快速排序(英語:Quicksort),又稱划分交換排序(partition-exchange sort),一種排序算法,最早由東尼·霍爾提出。在平均狀況下,排序
個項目要
(大O符號)次比較。在最壞狀況下則需要
次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他
算法更快,因為它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。
實現思想
快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。
步驟為:
- 從數列中挑出一個元素,稱為"基准"(pivot),
- 重新排序數列,所有比基准值小的元素擺放在基准前面,所有比基准值大的元素擺在基准后面(相同的數可以到任何一邊)。在這個分區結束之后,該基准就處於數列的中間位置。這個稱為分區(partition)操作。
- 遞歸地(recursively)把小於基准值元素的子數列和大於基准值元素的子數列排序。
遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個算法一定會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最后的位置去。
借用下啊哈算法的圖:

i和j分別為左哨兵和右哨兵,這里樞紐元定為6,然后分別從左往右(i++)和右往左(j--)開始遍歷
左哨兵查找比6大的元素,右哨兵查找比6小的元素
第一次交換結果


第二次交換結果



相遇后直接與樞紐元交換


然后再遞歸排序就行

快排核心算法代碼
1 public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) { 2 /* 3 * 當數組不小於3時,才推薦使用快排 4 * */ 5 if(left+CUTOFF<=right) 6 { 7 //取出樞紐元,樞紐元的位置為right-1 8 T privot=median3(a, left, right); 9 10 int i=left,j=right-1; 11 for(;;) 12 { 13 while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍歷 14 while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍歷 15 if(i<j) 16 swapReferences(a, i, j); 17 else 18 break; 19 } 20 /* 21 * for循環終止條件為i和j相遇,此時再將樞紐元歸位 22 * */ 23 swapReferences(a, i, right-1); 24 25 quicksort(a, left, i-1);//對左半部進行遞歸 26 quicksort(a, i+1, right);//對右半部進行遞歸 27 } 28 else 29 {} 30 }
全部代碼實現
1 public class MyQuickSort { 2 private static final int CUTOFF=3; 3 public static <T extends Comparable<? super T>> void quicksort(T[] a) { 4 quicksort(a,0,a.length-1); 5 } 6 public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) { 7 /* 8 * 當數組不小於3時,才推薦使用快排 9 * */ 10 if(left+CUTOFF<=right) 11 { 12 //取出樞紐元,樞紐元的位置為right-1 13 T privot=median3(a, left, right); 14 15 int i=left,j=right-1; 16 for(;;) 17 { 18 while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍歷 19 while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍歷 20 if(i<j) 21 swapReferences(a, i, j); 22 else 23 break; 24 } 25 /* 26 * for循環終止條件為i和j相遇,此時再將樞紐元歸位 27 * */ 28 swapReferences(a, i, right-1); 29 30 quicksort(a, left, i-1);//對左半部進行遞歸 31 quicksort(a, i+1, right);//對右半部進行遞歸 32 } 33 else 34 {} 35 } 36 /* 37 * 數組中數值交換 38 * */ 39 public static <T> void swapReferences(T[] a,int index1,int index2) { 40 T tmp=a[index1]; 41 a[index1]=a[index2]; 42 a[index2]=tmp; 43 } 44 /* 45 * 確定樞紐元,樞紐元的位置放在right-1位置 46 * */ 47 private static <T extends Comparable<? super T>> T median3(T[] a,int left,int right) { 48 int center=(left+right)/2; 49 if(a[center].compareTo(a[left])<0) 50 swapReferences(a, left, center); 51 if(a[right].compareTo(a[center])<0) 52 swapReferences(a, center, right); 53 if(a[right].compareTo(a[left])<0) 54 swapReferences(a, left, right); 55 56 swapReferences(a, center, right-1); 57 return a[right-1]; 58 } 59 }

個項目要
(大O符號)次比較。在最壞狀況下則需要
次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他