首页 > 代码库 > 普林斯顿公开课 算法3-3:三路快排

普林斯顿公开课 算法3-3:三路快排

很多时候排序是为了对数据进行归类,比如对城市进行排序,对员工的职业进行排序。这种排序的特点就是重复的值特别多。


如果使用普通的快排对这些数据进行排序,会造成N^2复杂度,但是归并排序和三路快排就没有这样的问题。


三路快排


三路快排的基本思想就是,在对数据进行分区的时候分成左中右三个部分,中间都是相同的值,左侧小于中间,右侧大于中间。


性能


三路快排的复杂度比普通快排小,主要取决于数据中重复数据的数量。重复数据越多,三路快排的复杂度就越接近于N。


代码

public class Quick3 {
    public static void sort(Comparable[] a) {
        Shuffle.shuffle(a);
        sort(a, 0, a.length);
    }
 
    public static void sort(Comparable[] a, int lo, int hi) {
        // 如果数组长度为0,直接返回
        if(lo >= hi) {
            return;
        }
 
        // 将第一个元素作为分区依据
        Comparable mid = a[lo];
 
        // 对数组进行扫描,分区
        int lt = lo;
        int gt = hi-1;
        int i = lo;
        while(true) {
            // 指针发生了交叉,退出循环
            if(i > gt) { // 注意,这里不是i >= gt,i=gt的时候仍然需要排序
                break;
            }
 
            int cmp = a[i].compareTo(mid); // 注意,这里不要用SortUtil.less
 
            if(cmp < 0) {
                SortUtil.exch(a,lt,i);
                lt++;
                i++;
            } else if(cmp > 0) {
                SortUtil.exch(a,gt,i);
                gt--;
            } else {
                // 跳过等值的情况。这就是为什么三路快排适合排序等值多的数组
                i++;
            }
        }
 
        // 迭代排序
        sort(a,lo,lt);
        sort(a,gt+1,hi);
    }
}