? ? ? ? ? ? ? ? if(i == high)
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ?
? ? ? ? ? ? while(a[--j]>a[low])
? ? ? ? ? ? ? ? if(j == low)
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ?
? ? ? ? ? ? if(i >= j)
? ? ? ? ? ? ? ? break;
? ? ? ? ? ?
? ? ? ? ? ? change(a,i,j);
? ? ? ? }
? ? ? ? change(a,low,j);
? ? ? ? System.out.println("low: " + low);
? ? ? ? return j;
? ? }
? ?
? ? public static void main(String[] args) {
? ? ? ? Integer[] a = {2,1,5,9,0,6,8,7,3};
? ? ? ? (new QuickSort()).sort(a);
? ? }
? ?
}
平均时间复杂度NlogN
三向快速排序
实际情况中经常会出现含有大量重复元素的数组,例如我们可能需要将大量人员资料按照生日排序,或是按照性别区分。在这些情况下,快速排序算法性能尚可,但还有巨大的改进空间,这就是三向快速排序。
简单的说,三向快速排序的原理为:将数组切分成三部分们分别对应于小于、等于、
大于切分元素的数组元素。与快速排序相比,增加了一个等于切分元素的区域。
流程如下:
从做到右遍历数组一次,维护一个指针lt使得a[low…lt-1]中的元素都小于v,一个指针gt使得a[gt+1…high]中的元素都大于 v,一个指针i使得a[lt…i-1]中的元素都等于v,a[i…gt]中的元素都还为确定,一开始i和lo相等。
使得i递增,对于a[i]:
a[i]小于v,将a[lt]和a[i]交换,将lt和i加一
a[i]大于v,将a[gt]和a[i]交换,将gt减一
a[i]等于v,将i加一
最后使数组呈现下图中的情况:
实现代码:
? ? public void quickSort3Way(Integer[] a,Integer low,Integer high) {
? ? ? ? if(low >= high)
? ? ? ? ? ? return;
? ? ? ?
? ? ? ? Integer lt = low;
? ? ? ? Integer i = low + 1;
? ? ? ? Integer gt = high;
? ? ? ? while(i<=gt) {
? ? ? ? ? ? if(a[i] < a[lt]) {
? ? ? ? ? ? ? ? change(a,i,lt);
? ? ? ? ? ? ? ? i++;
? ? ? ? ? ? ? ? lt++;
? ? ? ? ? ? } else if(a[i] > a[lt]) {
? ? ? ? ? ? ? ? change(a,i,gt);
? ? ? ? ? ? ? ? //这里不能使用i--,因为交换a[gt]和a[i]后,现在的a[i]并没有确定位置,如果使用i++,就将跳过交换后该元素的排序
? ? ? ? ? ? ? ? gt--;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? i++;
? ? ? ?