public static int partition(int[] a,int lo,int hi){
int i = lo , j = hi + 1;
int v = a[lo];
while(true){
while((a[++i]-v) < 0) {
// if(i == hi){
// break;
// }
}
while((v-a[--j]) < 0) {
// if(j == lo){
// break;
// }
}
if(i >= j) {
break;
}
exch(a,i,j);
}
exch(a,lo,j);
return j;
}
快速排序的核心——partition分割:在数组a中,选定第一个元素为标准元素(为了排除对输入了依赖性,在此函数调用之前对数组随机打乱),使i,j分别指向要比较数组的头与尾,while((a[++i]-v) < 0)与while((v-a[--j]) < 0) 分别指向从左至右小于/ 从右至左大于标准元素的元素的位置。并将它们的位置交换。当i>=j时,将标准元素放置数组中合适的位置上。
public static void quickSort(int[] a){
quickSort(a, 0, a.length - 1);
}
public static void quickSort(int[] a,int lo,int hi){
if(hi <= lo) return;
int j = partition(a,lo,hi);
quickSort(a,lo,j-1);
quickSort(a,j+1,hi);
}
递归调用发生在分割数组之后(与自顶向下的归并排序处理数组在归并之前),快速排序平均时间复杂度NlnN,最坏时间复杂度N平方。
当待排序数组中有大量重复元素时,可采用三取样切分来分割数组。
private static void sort(int[] a,int lo,int hi){
if(hi <= lo) return;
int lt = lo, i = lo+1, gt = hi; //li,i,gt 分别为< = > 标准数的位置
int v = a[lo];
while(i <= gt)
{
int b = a[i] - v;
if(b < 0) exch(a,lt++,i++);
else if(b == 0) i++;
else if(b > 0) exch(a,i,gt--);
}
sort(a,lo,lt-1);
sort(a,gt+1,hi);
}
在有大量重复数据时,三向切分排序的性能比快速排顺序好(最坏情况就是所有主键都不相同),可达到线性级别。