快排概念
快速排序(英语: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 }