• 快速排序


    快速排序比一般的排序算法都要快,它是原地排序(只需要一个很小的辅助数组),且将长度为N的数组排序所需的时间与NlgN成正比.

    基本算法

    快速排序也是一种分治算法,它将一个数组分成两部分分别排序,它和归并排序是互补的.

    归并排序是将一个数组分成两个子数组分别排序,并将有序子数组归并以将整个数组排序;而快速排序将数组排序的方式是子数组有序时整个数组也是有序的.

    在快速排序中,切分的位置取决于数组的内容.

    代码实现

        public static void sort(Comparable[] a){
            sort(a,0,a.length-1);
        }
        
        public static void sort(Comparable[] a, int lo, int hi){
            if(lo>=hi) return ;//递归出口
            int j = partition(a,lo,hi);    //切分元素
            sort(a,lo,j-1);    //左半部分排序
            sort(a,j+1,hi);    //右半部分排序
        }

    快速排序递归地将子数组a[lo..hi]排序,先用partition()方法将a[j]放到一个合适的位置,然后再递归将其他元素排序.

    关键在于切分,这个过程使数组满足三个条件:

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

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

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

    切分方法的实现

    先随意取a[lo]作为切分元素,即那个会被排定的元素.

    然后从数组的左端扫描直到找到一个大于等于它的元素,再从数组的右边扫描直到找到一个小于等于它的元素. 这两个元素显然没有排定,所以我们交换他们的位置

    如此继续,我们可以保证左指针i的左侧元素都不大于切分元素,右指针j的右侧元素都不小于切分元素. 当两个指针相遇时,我们只要把切分元素a[lo]和左子数组最右边元素a[j]进行交换即可,这时切分元素就留在了a[j]中了.

     

    轨迹图

    算法实现

        public static int partition(Comparable[] a, int lo, int hi){
            int i = lo, j = hi + 1;    //左右扫描指针
            Comparable v = a[lo];    //切分元素
            while(true){
                //扫描到左半部分大于v的元素停止
                while(less(a[++i], v)) if(i==hi) break;
                //扫描到右半部分小于v的元素停止
                while(less(v,a[--j])) if(j==lo) break;
                if(i>=j)
                    break;
                //交换元素
                exch(a,i,j);
            }
            //交换切分元素a[lo]和左半部分最右边的元素a[i].因为a[lo]到a[j-1]中的所有元素都不大于a[j]
            exch(a,i,lo);
            return j;
        }

    优化

    1.在排序小数组时切换到插入排序

    2.三取样切分(取样大小为3设中间的元素为切分元素),代价是需要计算中位数.

    3.熵最优排序

     三向切分的快速排序

    快速排序的一种改进,使快排在有大量重复元素的数据,同样能保持高效。

    我们从左到右遍历数组,维护一个指针lt使得a[lo..lt-1]中的元素全部小于v,一个指针gt使得a[gt+1..hi]中的元素全部大于v,一个指针i使得a[lt,i-1]中的元素都等于v,a[i,gt]中的元素都还未确定.

     

    一开始令i和lo相等,遍历过程中有3种情况

    a[i] < v, 将a[i]和a[lt]交换,将lt和i都加一.

    a[i] > v, 将a[i]和a[gt]交换,将gt减一.

    a[i] == v ,将i加一.

    这些操作保证数组元素不变且缩小gt-i的值(这样循环才能终止)

        public static void sort(Comparable[] a, int lo, int hi){
            if(hi <= lo) return ;
            int lt = lo, gt = hi,i = lo + 1;
            Comparator v = a[lo];
            while(i<=gt){
                int cmp = a[i].compareTo(v);
                if(cmp>0) exch(a,i,gt--);
                else if(cmp<0) exch(a,i++,lt++);
                else    i++;
            }
            //现在 a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]成立
            sort(a,lo,lt-1);
            sort(a,gt+1,hi);
        }

     算法轨迹

  • 相关阅读:
    使用jquery的js的页面实现例子
    Jmeter文章索引贴
    使用Jmeter进行http接口测试
    如何利用JMeter模拟超过 5 万的并发用户
    APP测试功能点总结
    软件测试面试题汇总
    python编程基础:《http://www.cnblogs.com/wiki-royzhang/category/466416.html》
    LoadRunner培训初级教程
    LoadRunner性能测试过程/流程
    【转】正则表达式30分钟入门教程
  • 原文地址:https://www.cnblogs.com/tanxing/p/5608608.html
Copyright © 2020-2023  润新知