快速排序算法


分而治之D&C

分而治之不是一種解決問題的算法,而是一種希望問題分解,將復雜的問題划分為多個簡單問題來解決的思想。

分而治之的思想重點:

(1)找出簡單的基線條件

(2)確定如何縮小問題的規模,使其符合基線條件。

快速排序

例如快速排序問題,一個列表進行排序,如下圖

首先選擇列表中的一個元素作為基准元素,其他的元素都與這個元素做比較,找出小於這個基准值的值、大於基准值的值。這稱為“分區”,這時有,

1)一個由所有小於基准值的數字組成的子數組;

2)基准值

3)一個由所有大於基准值的數組組成的子數組

然后再將“小於v”和“大於v”的數據塊作為子數組,同樣選擇基准值,再進行上述類似操作,當執行到數據塊中只有1個元素或者0個元素時,即完成排序。

這個問題中的基線條件是執行到數據塊中只有1個或者0個元素;

例如下面的數組,進行排序:

根據選擇的基准值,對這個數組進行分區的各種可能方式如下:

假設你將3用作基准值,可對得到的子數組進行快速排序。

還有一個例子,如下圖:


             

算法復雜度

看一下其他的算法的復雜度(O表示法表示)

快速排序的性能高度依賴於你選擇的基准值。

最糟情況:算法復雜度O(n^2)

假設總是將第一個元素用作基准值,且要處理的數組是有序的。由於快速排序算法不檢查輸入數組是否有序,因此它依然嘗試對其進行排序。

注意,數組並沒有被分成兩半,相反,其中一個子數組始終為空,這導致調用棧非常長。

這個示例展示的是最糟情況,在最糟情況下,棧長為O(n),在調用棧的每層都涉及O(n)個元素,完成每層所需的時間都為O(n)。因此整個算法需要的時間為O(n) * O(n) = O(n^2)。

最佳情況:算法復雜度O(n log n)

假設總是將中間的元素用作基准值,在這種情況下,調用棧如下。

調用棧短得多!因為每次都將數組分成兩半,所以不需要那么多遞歸調用。很快就到達了基線條件,因此調用棧短得多。

這個示例展示的是最佳情況,在最佳情況下,棧長為O(log n),每一層運行時間為O(n),所以整個算法需要的時間為O(n) * O(log n) = O(n log n)。

平均情況:算法復雜度O(n log n)

最佳情況也是平均情況。只要每次都隨機地選擇一個數組元素作為基准值,快速排序的平均運行時間就將為O(n log n)。快速排序是最快的排序算法之一,也是D&C典范。

如何選擇基准值?

實現快速排序時,請隨機地選擇用作基准值的元素。快速排序的平均運行時間為O(n log n)。

總結

1)D&C將問題逐步分解。使用D&C處理列表時,基線條件很可能是空數組或只包含一個元

素的數組。

2)實現快速排序時,請隨機地選擇用作基准值的元素。快速排序的平均運行時間為O(n log n)。

3)大O表示法中的常量有時候事關重大,這就是快速排序比合並排序快的原因所在。

快速排序詳解:http://c.biancheng.net/view/198.html

實例:

#include <stdio.h>
int qusort(int s[],int start,int end)    //自定義函數 qusort()
{
    int i,j;    //定義變量為基本整型
    i=start;    //將每組首個元素賦給i
    j = end;    //將每組末尾元素賦給j
    s[0]=s[start];    //設置基准值
    while(i<j)
    {
        while(i<j&&s[0]<s[j])
        j--;    //位置左移
        if(i<j)
        {
            s[i]=s[j];    //將s[j]放到s[i]的位置上
            i++;    //位置右移
        }
        while(i<j&&s[i]<=s[0])
            i++;    //位置左移
        if(i<j)
        {
            s[j]=s[i];    //將大於基准值的s[j]放到s[i]位置
            j--;    //位置左移
        }
    }
    s[i]=s[0];    //將基准值放入指定位置
    if (start<i)
        qusort(s,start,j-1);    //對分割出的部分遞歸調用qusort()函數
    if (i<end)
        qusort(s,j+1,end);
    return 0;
}

int main()
{
    int a[11], i;    //定義數組及變量為基本整型
    printf("請輸入10個數:\n");
    for(i=1;i<=10;i++)
        scanf("%d",&a[i]);    //從鍵盤中輸入10個要進行排序的數
    qusort(a,1,10);    //調用qusort()函數進行排序
    printf("排序后的順序是:\n");
    for(i=1;i<=10;i++)
        printf("%5d",a[i]);    //輸出排好序的數組
    printf("\n");
    return 0;
}

運行結果:

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM