2.5 3-way quickSort

1.排序时,数组含有大量重复元素,应该使用哪种排序手段?

(1)mergeSort:与数组的特征无关,比较次数总是在1/2NlgN~NlgN之间

(2)quickSort:当所有的元素全都相同的时候,使用平方次时间

2.3-way  partitioning算法的目标:

 将数组划分为3部分:

(1)lt和gt之间的元素等于v

(2)lt的左边元素小于v

(3)gt的右边元素大于v

3.Dijkstra的3-way partitioning算法:

(1)划分元素v是a[lo]

(2)scan i  from left to right

①a[i]<v:交换a[i]和a[lt],同时增大lt和i

②a[i]>v:交换a[i]和a[gt],减小gt

③a[i]==v:增大i(也就是不移动相等的元素)

i指向未遍历的元素,lt左边是比v小的,gt右边是比v大的,lt与i之间的是等于v的元素。

这个操作保证了等于v的元素 in place,接下来只需要分别对大于v和小于v的两个部分分别排序。

4.如果打乱数组,并且使用3-way partitioning,很多应用运行时间会是线性时间,会比mergesort快很多。

5.算法实现

package com.cx.sort;

public class Quick3way {
    public static void sort(Comparable[] a) {
        //打乱数组
        Shuffling.sort(a);
        sort(a,0,a.length-1);        
    }
    
    public static void sort(Comparable[] a,int lo,int hi) {
        if(hi<=lo) return;
        int lt=lo,gt=hi,i=lo;
        Comparable v=a[lo];
        //只要i和gt不重叠就要继续进行
        //完成后,lt左边小于v,gt右边大于v,lt..gt等于v
        while(i<=gt) {
            int cmp=a[i].compareTo(v);
            //a[i]<v,交换a[lt]和a[i]
            if(cmp<0) exch(a, i++, lt++);
            //a[i]>v,交换a[i]和a[gt]
            else if(cmp>0) exch(a, i, gt--);
            //保证等于v的元素in place
            else i++;                                
        }
        //递归排序lt左侧和gt右侧部分
        sort(a, lo, lt-1);
        sort(a, gt+1, hi);        
    }
    
    private static boolean less(Comparable v,Comparable w) {
        return v.compareTo(w)<0;
    }
    
    private static void exch(Comparable[] a,int i ,int j ) {
        Comparable t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
    private static void show(Comparable[] a) {
        for(int i=0;i<a.length;i++) {
            System.out.print(a[i]+" ");
            
        }
        System.out.println();
    }
    public static void main(String[] args) {
        String a[]= {"s","o","r","t","e","x","a","m","p","l","e"};
        show(a);
        sort(a);
        show(a);
    }
}
原文地址:https://www.cnblogs.com/sunnyCx/p/8177421.html