遞歸與分治策略之快速排序

我在前面的文章中寫道:遞歸與分治策略之線性選擇,在其中提到求在一個序列中第k小元素;它實現的算法思想就是利用快速排序的算法思想,那我們現在就一起探討一下快速排序。

 

快速排序算法也是基於分治策略的一個排序算法,當然還有另外一個歸併排序,也是基於分治策略的。其算法思想:對於輸入的子數組a[p:r],按一下三個步驟進行排序;

(1)分解:以a[p]爲基準元素將a[p:r],劃分成3段a[p,q-1],a[q]和a[q+1,r],使a[p,q-1]中任何一個元素不大於a[q],而a[q+1,r]中任何一個元素不小於a[q]。

(2)遞歸求解:通過遞歸調用快速排序算法分別對a[p,q-1]和a[q+1,r],進行排序。

(3)合併:由於對a[p,q-1]a[q+1,r]的排序是就地進行的,所以在a[p,q-1]和a[q+1,r]都已排好的序後,不需要執行任何計算。

基於這個思想,可實現快速排序算法如下:

 

int Partition(int low, int high, int a[])
{
    a[0] = a[low];
    int pivotkey = a[low];
    while(low < high)
    {
        while(low < high && a[high] >= pivotkey) high--;
        a[low] = a[high];
        while(low < high && a[low] <= pivotkey) low++;
        a[high] = a[low];
    }
    a[low] = a[0];

    return low;
}

void QiuckSort(int low, int high, int a[])
{
    int pivotloc = 0;
    if(low < high)
    {
        pivotloc = Partition(low, high, a);
        QiuckSort(low, pivotloc-1, a);
        QiuckSort(pivotloc+1, high, a);
    }
}

 

很容易證明,快速排序在平均情況下的時間複雜度是O(nlogn);並且在所有同數量級的排序算法中,其平均性能最好。但是若初始序列是有序或者基本上是有序的,快速排序就蛻化爲冒泡排序了。對於上面的快排算法還是有優化的空間。

很容易看到,快速排序算法的性能是取決於劃分對稱性。通過修改Partition函數,可以設計出採用隨機選擇的快速排序算法。在快速排序算法的每一步中選擇劃分基數改爲隨機的,從而可以期望劃分是較對稱的。隨機化的劃分算法可實現如下:

 

int RandomizedPartion(int low, int high, int a[])
{
    int i = Random(low, high);
    swap(a[low], a[i]);
    return Partition(a, p, r);
}


 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章