排序演算法總結之快速排序

來源:互聯網
上載者:User

標籤:快速排序   java   

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,通常稱其為分治法(Divide-and-ConquerMethod)。

分治法的基本思想
    分治法的基本思想是:將原問題分解為若干個規模更小但結構與原問題相似的子問題。遞迴地解這些子問題,然後將這些子問題的解組合為原問題的解。

快速排序的基本思想

從待排序的資料序列中任取一個資料(如第一個資料)作為分界值,所有比它小的資料元素一律放到左邊,所有比它大的資料元素放到右邊。這樣一趟後,就形成了兩個子序列:左序列中的資料都比分界值小,右序列的資料元素都比分界值大。

然後,對左、右兩個子序列遞迴進行上述操作,直到每個子序列只剩一個元素。

從上面的演算法分析可以看出,實現快速排序的關鍵在於第一趟要做的事情:

(1)選出指定的基準(PivotKey)

(2)將所有小於分界值的資料元素放在左邊

(3)將所有大於分界值的資料元素放到右邊

主要是如何?2、3兩步!

排序效果:

Java實現代碼:
package com.liuhao.sort;import java.util.Arrays;/*** 快速排序的Java實現* @author liuhao**/public class QuickSort {    /**     * @param data     * @param start     * @param end     */    private static int subSort(DataWrap[] data, int start, int end){        DataWrap tmp = data[start];        while(start < end){            while( start < end && data[end].compareTo(tmp) >= 0){                end--;            }            data[start] = data[end];                       while(start < end && data[start].compareTo(tmp) <= 0){                start++;            }            data[end] = data[start];        }               data[end] = tmp;               System.out.println(Arrays.toString(data));               return start;    }       /**     * 遞迴進行快速排序     * @param data     * @param start     * @param end     */    public static void quickSort(DataWrap[] data, int start, int end){        if(start < end){            int key = subSort(data, start, end);            quickSort(data, start, key-1);            quickSort(data, key+1, end);        }    }       public static void main(String[] args) {        DataWrap[] data = {                new DataWrap(21, "")                ,new DataWrap(30, "")                ,new DataWrap(49, "")                ,new DataWrap(30, "*")                ,new DataWrap(16, "")                ,new DataWrap(9, "")        };               System.out.println("排序之前:" + Arrays.toString(data));        quickSort(data, 0, data.length-1);        System.out.println("排序之後:" + Arrays.toString(data));    }   }
運行結果:

演算法分析

快速排序的時間主要耗費在劃分操作上,對長度為k的區間進行劃分,共需k-1次關鍵字的比較。
(1)最壞時間複雜度
    最壞情況是每次劃分選取的基準都是當前無序區中關鍵字最小(或最大)的記錄,劃分的結果是基準左邊的子區間為空白(或右邊的子區間為空白),而劃分所得的另一個非空的子區間中記錄數目,僅僅比劃分前的無序區中記錄個數減少一個。
    因此,快速排序必須做n-1次劃分,第i次劃分開始時區間長度為n-i+1,所需的比較次數為n-i(1≤i≤n-1),故總的比較次數達到最大值:
               Cmax = n(n-1)/2=O(n2)
    如果按上面給出的劃分演算法,每次取當前無序區的第1個記錄為基準,那麼當檔案的記錄已按遞增序(或遞減序)排列時,每次劃分所取的基準就是當前無序區中關鍵字最小(或最大)的記錄,則快速排序所需的比較次數反而最多。
(2) 最好時間複雜度
    在最好情況下,每次劃分所取的基準都是當前無序區的"中值"記錄,劃分的結果是基準的左、右兩個無序子區間的長度大致相等。總的關鍵字比較次數:
        0(nlgn)
注意:
    用遞迴樹來分析最好情況下的比較次數更簡單。因為每次劃分後左、右子區間長度大致相等,故遞迴樹的高度為O(lgn),而遞迴樹每一層上各結點所對應的劃分過程中所需要的關鍵字比較次數總和不超過n,故整個排序過程所需要的關鍵字比較總次數C(n)=O(nlgn)。
    因為快速排序的記錄移動次數不大於比較的次數,所以快速排序的最壞時間複雜度應為0(n2),最好時間複雜度為O(nlgn)。
(3)基準關鍵字的選取
    在當前無序區中選取劃分的基準關鍵字是決定演算法效能的關鍵。
①"三者取中"的規則
    "三者取中"規則,即在當前區間裡,將該區間首、尾和中間位置上的關鍵字比較,取三者之中值所對應的記錄作為基準,在劃分開始前將該基準記錄和該區伺的第1個記錄進行交換,此後的劃分過程與上面所給的Partition演算法完全相同。

②取位於low和high之間的隨機數k(low≤k≤high),用R[k]作為基準

    選取基準最好的方法是用一個隨機函數產生一個取位於low和high之間的隨機數k(low≤k≤high),用R[k]作為基準,這相當於強迫 R[low..high]中的記錄是隨機分布的。用此方法所得到的快速排序一般稱為隨機的快速排序。具體演算法【參見教材】
注意:
     隨機化的快速排序與一般的快速排序演算法差別很小。但隨機化後,演算法的效能大大地提高了,尤其是對初始有序的檔案,一般不可能導致最壞情況的發生。演算法的隨機化不僅僅適用於快速排序,也適用於其它需要資料隨機分布的演算法。
(4)平均時間複雜度
    儘管快速排序的最壞時間為O(n2),但就平均效能而言,它是基於關鍵字比較的內部排序演算法中速度最快者,快速排序亦因此而得名。它的平均時間複雜度為O(nlgn)。
(5)空間複雜度
    快速排序在系統內部需要一個棧來實現遞迴。若每次劃分較為均勻,則其遞迴樹的高度為O(lgn),故遞迴後需棧空間為O(lgn)。最壞情況下,遞迴樹的高度為O(n),所需的棧空間為O(n)。
(6)穩定性
    快速排序是非穩定的,例如[2,2,1]。

排序演算法總結之快速排序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.