快速排序

快速排序

实现原理:递归的将切分元素的左边和右边排序,优点是原地排序,而且速度快,时间复杂度是线性对数的

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;

public class Quick {
    public static void sort(Comparable[] a){
        StdRandom.shuffle(a);       //消除对输入的依赖,保持随机性的另一种方法是在partition中随机选取一个切分元素
        sort(a, 0, a.length - 1);
    }
    private static void sort(Comparable[] a, int lo, int hi){
        if(hi <= lo)
            return;
        int j = partition(a,  lo, hi);
        sort(a, lo, j - 1);         //将左半部分排序
        sort(a, j + 1, hi);         //将有半部分排序
    }
    private static int partition(Comparable[] a, int lo, int hi) {
        // TODO Auto-generated method stub
        int i = lo, j = hi + 1;
        Comparable v = a[lo];
        while(true){
            while(less(a[++i],v))       //获得比v大的数
                if(i == hi)
                    break;      
            while(less(v, a[--j]))      //获得比v小的数
                if(j == lo)
                    break;
            if(i >= j)                  //当i和j相遇时退出循环
                break;
            exch(a, i, j);
        }
        exch(a, lo, j);
        return j;
    }
    private static void exch(Comparable[] a, int i, int j) {
        // TODO Auto-generated method stub
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    private static boolean less(Comparable v, Comparable w) {
        // TODO Auto-generated method stub
        return v.compareTo(w) < 0;
    }
    public static void show(Comparable[] a) {
        // TODO Auto-generated method stub
        for(int i = 0; i <a.length;i++ )
            StdOut.print(a[i] + " ");
        StdOut.println();
    }
}

但是当数组过小时,快速排序的性能并不见得回比插入排序好,所以在递归时,判断数组大小是否小于某一个合适的常数,当小于这个常数时使用插入排序。将私有方法sort()进行改进。其他部分保持不变。

改进代码如下:

private static void sort(Comparable[] a, int lo, int hi){
        if(hi <= lo + 10){          //对于小数组使用插入排序性能比快速排序更好
            Insertion.sort(a, lo, hi);
            return;
        }
        int j = partition(a,  lo, hi);
        sort(a, lo, j - 1);         //将左半部分排序
        sort(a, j + 1, hi);         //将有半部分排序
    }

上面的优化解决了当数组过小时,性能较差的问题,但是当数组中重复元素很多时,快速排序任然会把大量时间话在对相等元素进行排序,下面这段代码是想了三向切分快速排序。它将数组分为小于切分元素,等于切分元素,大于切分元素三个部分,然后对小于和大于的部分进行排序,而等于的部分不动。

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;

public class Quick3way {
    public static void sort(Comparable[] a){
        StdRandom.shuffle(a);       //消除对输入的依赖,保持随机性的另一种方法是在partition中随机选取一个切分元素
        sort(a, 0, a.length - 1);
    }

    private static void sort(Comparable[] a, int lo, int hi) {
        // TODO Auto-generated method stub
        if(hi <= lo)
            return;
        int lt = lo,i = lo + 1, gt = hi;    //a[lo...lt-1]小于v,a[lt...i-1]等于1,a[i...gt]不确定,a[gt+1...hi]大于1
        Comparable v = a[lo];
        while(i <= gt){
            int cmp = a[i].compareTo(v);
            if(cmp < 0)
                exch(a,lt++, i++);  //将a[lt]和a[i]交换
            else if(cmp > 0)
                exch(a, i, gt--);   //i不需要在进行自增操作,因为a[gt]这个元素还没有和v比较
            else i++;
        }
        sort(a, lo, lt - 1);        //对小于v的元素进行排序
        sort(a, gt + 1, hi);        //对大于v的元素进行排序
    }
    private static void exch(Comparable[] a, int i, int j) {
        // TODO Auto-generated method stub
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    private static boolean less(Comparable v, Comparable w) {
        // TODO Auto-generated method stub
        return v.compareTo(w) < 0;
    }
    public static void show(Comparable[] a) {
        // TODO Auto-generated method stub
        for(int i = 0; i <a.length;i++ )
            StdOut.print(a[i] + " ");
        StdOut.println();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值