排序––快速排序(二)

根據排序––快速排序(一)的描述,現準備寫一個快速排序的主體框架:算法

一、首先須要設置一個樞軸元素即setPivot(int i);框架

二、而後根據樞軸元素進行劃分,將比樞軸元素大的排在右邊,小的排在左邊; .net

三、分別對樞軸元素左邊和右邊的序列重複1和2的步驟進行劃分,這是一個遞歸過程,整個代碼框架很簡單:blog

public void sort(int from, int to) {
        if (from >= to) {
            return;
        }
        setPivot(from);
        int partitionPos = partition(from, to);
        sort(from, partitionPos - 1);
        sort(partitionPos + 1, to);
  }排序

  每一個子序列返回的條件是from >= to,因爲樞軸元素是隨機選擇的,因此有如下幾種劃分狀況:遞歸

一、軸樞元素正好能將序列分紅均勻的兩半,若是是奇數個元素那麼子序列退出的條件是from==to,若是是偶數個元素如2個,那麼會出現from>to的狀況。get

二、軸樞元素不能將序列分紅均勻的兩半,最極端的狀況是軸樞元素將劃分的序列老是比它大或者小,此時一樣會出現from>to的狀況。it

實際上無論軸樞元素是否能將序列分紅均勻的兩半,只要序列的個數是偶數個必定會出現from>to的狀況!io

目前只描述了最終劃分結果可能出現的狀況,尚未說明如何劃分,下面給出一個劃分的方案:循環

    假設給定序列七、六、五、四、三、二、1,並選擇4爲樞軸,則示例代碼以下:

int   partition(int from, int to) {   
        int right = to;
        int left = from;
        while (true) {
            while (comparePivot(right) > 0) {
                right--;
            }

            while (comparePivot(left) < 0) {
                left++;
            }
            if (left == right) {
                break;
            }
            swap(left, right);
        }

        return left;
    }

     驗證一下:7和1進行交換,序列變成一、六、五、四、三、二、7;left=0;right=6;

                      6和2進行交換,序列變成一、二、五、四、三、六、7;left=1;right=5;

                      5和3進行交換,序列變成一、二、三、四、五、六、7;left=2;right=4;

                      left=3;right=3;退出循環

                      而後分別調用sort(0,2),sort(4,6),對於sort(0,2)的排序過程以下:

                       假設選取2爲樞軸,因爲原始序列已經有序,right=1;left=1;退出循環。 最後的兩個遞歸是sort(0,0)以及sort(2,2),這兩個遞歸會因爲from==to條件直接退出。

                      sort(4,6)也是相似的狀況。

                    最後整個序列就是有序序列,由此看來該程序貌似正確,可是此狀況比較特殊,爲了能適應通常的狀況,還需改進。其實正確的快速排序代碼量不多,可是要把各類狀況分析到位,寫一個正確的快速排序代碼我的認爲起碼沒有其它排序算法那麼簡單。

相關文章
相關標籤/搜索