一、双路快排思路
基于单路快排的基础上,若排序的数组中的元素重复多,所选的标定点是极度不平衡的话(数组两边位置不平衡),那么快速排序的时间复杂度会下降到O(n的2次方)
不平衡的情况:
换个思路:
设标记点为v,将小于v和大于v的两部分放到数组的两端,设j为大于v下一个数组要扫描的位置,设i为小于v下一个数组要扫描的位置,比如说扫描到中间的状态,如下图
那么,我们将从i位置向后扫描,当元素仍然小于v时继续向后扫描,直到碰到大于等于v的元素
同样,从j位置向前扫描,当元素仍然大于v时继续向前扫描,直到碰到小于等于v的元素
然后直接将i和j的位置交换就可以了,交换完后再重复以上步骤,直到i和j的位置重合,就是整个数组遍历完毕
最后把v放到j的位置上
二、双路快排实现:
private static void quickSort2(int array[],int l ,int r){
if(l>=r){
return;
}
int p = partition2(array,l,r);
quickSort2(array,l,p-1);
quickSort2(array,p+1,r);
}
private static int partition2(int[] array, int l, int r) {
//选取一个随机数
int pivot = array[l];
int i=l+1; int j = r;
while(true){
while(i<=r&&array[i]<pivot){i++;}
while(j>=l+1&&array[j]>pivot){j--;}
if(i>j) {break;}
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
int tmp = array[l];
array[l] = array[j];
array[j] = tmp;
return j;
}
private static void quickSort2(int array[],int n){
quickSort2(array,0,n-1);
}
三、注意要点
1.递归调用,必须要有退出条件。
2.注意数组越界问题。
3.保持随机性。要判断数组的顺序情况,若为一个严格倒序,对运行时间有要求时则要对排序算法作出优化;随机选择一个切分元素。
4.要保证循环终止的情况。需要恰当处理出现越界或重复元素时的循环情况。
5.原地切分数组。使用辅助数组会产生额外开销,若辅助数组为空数组,排序速度会大大降低。
6.要处理切分元素有重复的情况。