快速排序是一种分治的排序算法。它将一个数组分为两个数组,将两部分独立地排序。
快速排序递归地将子数组a[lo..hi]排序,先用partition()方法将a[j]放到一个合适的位置,然后再用递归调用将其他位置的元素排序。
该方法的关键在于切分,这个过程使得数组满足下面三个条件:
1.对于某个j,a[j]已经排定;
2.a[lo]到a[j - 1]中的所有元素都不大于a[j];
3.a[j + 1]到a[hi]的所有元素都不小于a[j]。
切分的一般策略是先随意的取a[lo]作为切分元素,即那个将会被排定的元素,然后我们从数组的左端开始向右扫描直到找到一个大于等于它的元素。再从数组的右端开始向左扫描直到找到一个小于等于它的元素
具体实现:
public static int partition(Comparable[] a, int lo, int hi){
Comparable v = a[lo];
int i = lo;
int j = hi + 1;
while (true){
while(less(a[++i], v)){
if(i == hi){
break;
}
}
while(less(v, a[--j])){
if(j == lo){
break;
}
}
if(j <= i){
break;
}
Example.exch(a, j , i);
}
Example.exch(a, j, lo);
return j;
}
public static void sort(Comparable[] a, int lo, int hi){
if(hi <= lo){
return;
}
int j = partition(a, lo, hi);
sort(a, lo , j - 1);
sort(a, j + 1, hi);
}
快速排序算法改进
1.切换到插入排序
(1)对于小数组,快速排序比插入排序慢;
(2)因为递归,快速排序的sort()方法在小数组中也会调用自己。
因此,在排序小数组时应该切换到插入排序。
三向切分的快速排序
public static void threeWaySort(Comparable[] a, int lo, int hi){
if(hi <= lo){
return;
}
int lt = lo, i = lo + 1, gt = hi;
Comparable v = a[lo];
while(i <= gt){
int cmp = a[i].compareTo(v);
if(cmp > 0){
Example.exch(a, i, gt--);
}else if(cmp < 0){
Example.exch(a, i++, lt++);
}else{
i++;
}
}//现在a[lo..lt-1] < v = a[lt..gt] < a[gt + 1..hi]
sort(a, lo, lt - 1);
sort(a, gt + 1, hi);
}