zoukankan      html  css  js  c++  java
  • 算法_快速排序

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

      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;
        }
    }

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

  • 相关阅读:
    索引虚拟oracle virtual index
    用户盘云存储——百度网盘
    数据类型泛型的嵌套使用
    函数返回值C语言中malloc函数返回值是否需要类型强制转换问题
    控制文件oracle controlfile structure
    程序语言POJ 2406 Power Strings
    数组信息[置顶] php数组转换js数组操作及json_encode应用
    代码电话《程序员的第一年》情感编
    泛型通配符泛型中使用 通配符
    数字字符串一道有道实习生笔试算法题分析
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5642923.html
Copyright © 2011-2022 走看看