看代码:
public static int[] partition(int[] arr,int i,int T)
{
int lt = i-1,gt = T;
while (i<gt) {
if(arr[i]==arr[T]) {
++i;
}
else if(arr[i]<arr[T]) {
swap(arr,++lt,i++);
}else{
swap(arr,--gt,i);
}
}
swap(arr,gt,T);
return new int[]{lt,gt+1};//lt==gt ?
}
public static void swap(int[] arr,int l,int r)
{
if(arr[l]==arr[r])return;
arr[l]^=arr[r];
arr[r]^=arr[l];
arr[l]^=arr[r];
}
public static void quickSort(int[] arr,int l,int r) {
if(r<=l) return;
swap(arr,l+(int)Math.random()*(r-l+1),r);
int[] eq = partition(arr,l,r);
quickSort(arr,l,eq[0]);
quickSort(arr,eq[1],r);
}
如图所示:
3路快速排序,
这一轮选择的基准点是 3
黄色的表示小于3的区域,蓝色的表示大于3的区域,绿色的表示等于3的区域
partition函数返回 lt,和gt+1 这个下标,即 在【lt+1,gt】这个区间里面
都是相等的元素,一定是有序的,剩下的就是排这个区间外的其他元素
排序选择的标定点最好与数据原本的顺序无关,使得标定点左右两边的区域的长度相等
这里我在 给定的 [l,r] 区间里面随机选择一个元素与 r位置的交换,也就是说标定点位置设为 r位置,我把这个位置用 T 表示
举个例子
lt部分推着 i走,当扫描指针i到达 gt位置的时候说明空白部分的长度为0,也就是说 这一轮的partiton 完成了
这时,把 gt指向的位置和 T所在的位置元素交换
把 lt位置和 gt+1位置返回,这就是下一轮要排序的范围