三路快速排序法

三路快速排序将数组分成了 <V, ==V, >V 三部分,这样只需递归的对<V和>V的部分进行快速排序
具体步骤演示:

处理e的各种情况



e == v, i++





e < v, e 和 arr[lt + 1] 交换, lt++, i++查看下一个元素




e > v, e 和 arr[gt - 1] 交换位置, gt--

当 i == gt : 表示对整个数组处理完毕


交换arr[l]和arr[lt], lt++
接下来只需对<v的部分和>v的部分进行递归排序就好了, ==v的部分已经放在了数组中合适的位置
这种方案的优点:不需对大量==v 的元素进行排序操作
快速排序和归并排序都是Nlog(N),但是快速排序比归并排序要快些
代码部分
public class ThreeWayQuickSort extends Sort {
private Random random;
public void sort(int[] arr, int n) {
random = new Random(new Date().getTime());
quickSort(arr, 0, n - 1);
}
/**
* 对arr[l..r]部分进行三路快速排序
* 将arr[l..r]分为<v, ==v, >v 三部分
* 然后递归对<v 和 >v 部分进行三路快速排序
*/
private void quickSort(int[] arr, int l, int r) {
if (l >= r) {
return;
}
if ( r - l <= 15) {//优化1:子序列元素个数小于16时用插入排序
AlgorithmUtils.insertionSort(arr, l, r);
return;
}
//由于三路快速排序的中间部分是==v的一个区间,java语言不好写出返回区间首尾的值,
//所以不单独写partition方法
AlgorithmUtils.swap(arr, l, Math.abs(random.nextInt()) % (r - l + 1) + l);
int v = arr[l];
int lt = l; //arr[l + 1..lt] < v //初始时 lt < l + 1, 为空区间
int i = l + 1; //arr[lt + 1..i - 1] == v
int gt = r + 1; //arr[gt..r] > v //初始时 r < gt , 为空区间
while (i < gt) {
if (arr[i] < v) {
AlgorithmUtils.swap(arr, i, lt + 1);
lt++;
i++;
}else if (arr[i] > v) {
AlgorithmUtils.swap(arr, i, gt - 1);
gt--;
}else {
i++;
}
}
AlgorithmUtils.swap(arr, l, lt);
quickSort(arr, l, lt - 1);
quickSort(arr, gt, r);
}
}

随时随地看视频