如何寫出一個較好的快速排序程序

寫出一個較好的快速排序程序

  • 快速排序是常用的排序算法之一,但要想寫出一個又快又準的使用程序,就不是那麼簡單了

需要注意的事項

  • 首先要寫正確。通常使用遞歸實現。其遞歸相當於二叉樹展開,因此如果要用迭代實現的話需要使用一個隊列來保存後續遍歷信息。
  • 快速排序需要找到一個pivot值,如果順序選擇pivot則易造成N^2的複雜度,如果使用隨機數則效果最好,但開銷又太大,採取三數中值法比較合適。三數中值法指的是選取第一個值,最後一個值,數組中間的值的中值。有文獻表明可以提升5%的運行時間。
  • 當數組長度較小時,如10個元素以下,最好使用插入排序或者選擇排序完成,以防止複雜度常數因子過大或多次函數調用帶來的開銷。而遞歸到底層數組長度總是會變小的,因此這麼做非常有必要。
  • 在合併前後兩部分數組時,採用兩邊夾方法,在前後兩部分各找到一個大於和小於的值再交換。相比通常情況下找到比pivot小的值就進行交換,能提高運行效率。

實現代碼

  • 代碼如下。包括插入排序insert_sort,遞歸函數,三分中值函數三個輔助函數。
  • 三分中值函數其實採用的是插入排序。通過三次比較,確定中值。
  • 插值算法使用臨時變量tmp避免了大量swap函數調用。
#include<iostream>
#include<iomanip>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<algorithm>

using namespace std;

inline void swap(vector<int>& num, int p, int q){
    int t = num[p];
    num[p] = num[q];
    num[q] = t;
}

void insert_sort(vector<int>& num){
    int tmp, j;
    for (int i = 1; i < num.size(); i++){
        tmp = num[i];
        for (j = i - 1; j >= 0 && num[j] > tmp; j--)
            num[j + 1] = num[j];
        num[j + 1] =tmp;
    }
}

int quick_sort_sub(vector<int>& num, int p, int q){
    if (p >= q)
        return 0;

    // if 4 elements or less, use insert sort
    if (p + 10 > q){
        vector<int> tnum(num.begin() + p, num.begin() + q + 1);
        insert_sort(tnum);
        for (int i = 0; i < tnum.size(); i++)
            num[p + i] = tnum[i];
    }

    int idx = quick_three_partition(num, p, q);
    swap(num, idx, q);

    int pivot = num[q];
    int left = p, right = q - 1;
    while (1){
        while (num[left] < pivot)
            ++left;
        while (num[right] >= pivot)
            --right;
        if (left < right)
            swap(num, left, right);
        else
            break;
    }
    swap(num, left, q);
    quick_sort_sub(num, p, left - 1);
    quick_sort_sub(num, left + 1, q);

    return left;
}

void quick_sort(vector<int>& num){
    quick_sort_sub(num, 0, num.size() - 1);
}

int main(){
    const int n = 10;
    /*int num_array[n]= {2,1};
    vector<int> num(num_array, num_array + n);*/

    srand( time(NULL) );
    vector<int> num(n);
    for (auto& e : num)
        e = rand() % n;

    quick_sort(num);


    for (auto& e : num)
        cout << setw(4) << e << ' ';
    cout << endl;

    cout << "vector is sorted? : " << is_sorted(num.begin(), num.end()) << endl;

    return 0;

}

 
 

轉載請註明作者:Focustc,博客地址爲http://blog.csdn.net/caozhk,原文鏈接爲點擊打開
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章