算法_快速排序

  快速排序是一种分治的排序算法.它将一个数组分成两个子数组,将两部分独立的排序.快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并并将整个数组排序,而快速排序将数组排序的方式则是当两个子数组都有序的时候,整个数组就自然有序了,切分是快速排序中最重要的操作.这个过程使得数组满足下面的条件:

  1.对于某个j,a[j]已经排定

  2.a[lo]到a[j-1]中的所有元素都不大于a[j].

  3.a[j+1]到a[hi]中的所有元素都不小于a[j].

  策略是先随意的取a[lo]作为切分元素,然后实现对a[lo]的交换.代码如下:

  

public class Quick {
    public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);
        sort(a,0,a.length-1);
    }

    public static void sort(Comparable[] a, int lo, int hi) {
        if(hi<=lo) return;
        int j=partition(a,lo,hi);    //j前的元素不大于a[j],j后的元素不小于a[j]
        sort(a,lo,j-1);
        sort(a,j+1,hi);
    }

    public static int partition(Comparable[] a, int lo, int hi) {
        int i=lo;
        int j=hi;
        Comparable v=a[lo];
        while(true) {
            while(less(a[++i],v)) {if(i==hi) break;}
            while(less(v,a[--j])) {if(j==lo) break;}
            if(i>=j) break;
            exch(a,i,j);
        }
        exch(a,lo,j);
        return j;
    }
    public static void exch(Comparable[] a, int i, int min) {
        Comparable t=a[i];
        a[i]=a[min];
        a[min]=t;
    }
    public static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w)<0;
    }
}

  快速排序最好的情况是每次都能正好将数组对半分,在这种情况下,快速排序所用的比较次数满足分治递归的CN=2CN/2+N公式.2CN/2表示子数组排序的成本,N表示用切分元素和所有数组元素进行比较的成本,这个递归方式的解CN~NlgN.平均而言,元素都能落在数组中间.

  为了防止有大量重复元素的情况下,排序性能下降(因为一个元素全部重复的数组就不用切分进行排序了,但是上面的算法依然会继续切分),有下面这种三切分的快速排序:

  维护一个指针lt使得a[lo..lt-1]中的元素小于v,一个指针gt使得a[gt+1..hi]中的元素都大于v,一个指针i使得a[lt..i-1]中的元素都等于v,a[i..gt]中的元素还未确定.

  代码如下:

  

public class Quick3way {
    public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);
        sort(a,0,a.length-1);
    }
    public static void sort(Comparable[] a, int lo, int hi) {
        if(hi<=lo) return;
        int lt=lo;
        int i=lo+1;
        int gt=hi;
        Comparable v=a[lo];
        while(i<=gt) {
            int cmp=a[i].compareTo(v);
            if(cmp<0) exch(a,lt++,i++);
            if(cmp>0) exch(a,gt--,i);
            else i++;
        }
        sort(a,lo,lt-1);
        sort(a,gt+1,hi);
    }
    public static void exch(Comparable[] a, int i, int min) {
        Comparable t=a[i];
        a[i]=a[min];
        a[min]=t;
    }
    public static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w)<0;
    }
}

  三向切分的快速排序对于包含大量重复的元素,它将排序时间从线性对数级别降低到了线性级别.

posted @ 2016-07-05 11:16  hlhdidi  阅读(249)  评论(0编辑  收藏  举报