資料結構與演算法——快速排序

readyao發表於2016-01-12

快速排序介紹:

平均時間複雜度為O(NlogN),最壞的情況是O(N^2)。

快速排序是不穩定的,不能保證相等元素原來的排序順序。參考部落格:為什麼快速排序是不穩定的


原始碼:

/*************************************************************************
	> File Name: quicksort.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016???1???2???星期???16???3???1???
 ************************************************************************/

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;

//這是插入排序的演算法,用於排序數量小於10的序列
void insert_sort(vector<int> & data, int left, int right)
{
    int j;
    for (int i = left + 1; i <= right; ++i){
        int tmp = data[i];
        for (j = i; j > 0 && tmp < data[j-1]; j--){
            data[j] = data[j-1];
        }
        data[j] = tmp;
    }
}

//獲得樞紐元
template<class T>
const T & median3(vector<T> & a, int left, int right)
{
    int center = (left+right)/2;
    
    if(a[center] < a[left])
        swap(a[center], a[left]);
    if(a[right] < a[left])
        swap(a[right], a[left]);
    if(a[right] < a[center])
        swap(a[center], a[right]);

    //將樞紐元和最後一個元素互換位置
    swap(a[center], a[right-1]);
    return a[right-1];
}

//快速排序演算法
template<class T>
void quicksort(vector<T> & a, int left, int right)
{
    //排序的元素的個數大於10,選擇快速排序,
    if (left + 10 <= right){
        T pivot = median3(a, left, right);//獲得樞紐元

        //開始排序
        int i = left, j = right - 1;
        for ( ; ; ){
            while(a[++i] < pivot){}
            while(a[--j] > pivot){}

            if(i < j)
                swap(a[i], a[j]);
            else
                break;
        }

        swap(a[i], a[right-1]);//恢復樞紐元的位置

        quicksort(a, left, i-1);
        quicksort(a, i + 1, right);
    }
    else{
        //排序的元素的個數小於10,用插入排序演算法來排序
        insert_sort(a, left, right);
    }
}

int main()
{
    vector<int> v;
    v.push_back(23);
    v.push_back(12);
    v.push_back(9);
    v.push_back(34);
    v.push_back(11);
    v.push_back(7);
    v.push_back(3);
    v.push_back(10);
    v.push_back(8);
    v.push_back(25);
    v.push_back(89);
    v.push_back(11);
    v.push_back(90);
    v.push_back(100);
    v.push_back(45);
    v.push_back(28);
    v.push_back(26);

    cout << "v: ";
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    quicksort(v, 0, v.size() -1); 

    cout << "quicksorted v: ";
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    return 0;
}



下面的例子是將陣列的第一個元素作為基準元素:

/*************************************************************************
	> File Name: quicksort2.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016年04月17日 星期日 15時36分03秒
 ************************************************************************/

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;


//快速排序
void quickSort(vector<int> & v, int first, int last)
{
    int value = v[first];//基準數字
    
    if(first >= last)
        return;

    int i = first;
    int j = last;

    while(i < j){

        while(v[j] >= value && i < j)
            j--;

        while(v[i] <= value && i < j)
            i++;

        swap(v[i], v[j]);
    }

    v[first] = v[i];//將中間的數字放入第一個位置,是為了將中間的數字作為基準數字
    v[i] = value;//將基準數字重新中間
    

    quickSort(v, first, i-1);
    quickSort(v, i+1, last);
}

//主函式
int main()
{
    srand(unsigned(time(0)));

    vector<int> v;

    for(int i = 0; i < 10; ++i)
        v.push_back(rand()%10);

    cout << "v: ";
    for(int i = 0; i < 10; ++i)
        cout << v[i] << " ";
    cout << endl;

    quickSort(v, 0, v.size()-1);

    cout << "After sort: ";
    for(int i = 0; i < 10; ++i)
        cout << v[i] << " ";
    cout << endl;

    return 0;
}


在程式中一定要注意的是:

while(v[j] >= value && i < j)
            j--;

while(v[i] <= value && i < j)
            i++;

這個順序一定不能反過來,必須先從右邊開始判斷。


程式輸出結果為:

v: 2 8 7 6 0 4 4 0 9 9 
After sort: 0 0 2 4 4 6 7 8 9 9 
root@linux_ever:~/linux_ever/algorithm/ch7# ./quicksort2
v: 2 4 3 4 5 4 0 8 8 7 
After sort: 0 2 3 4 4 4 5 7 8 8 
root@linux_ever:~/linux_ever/algorithm/ch7# ./quicksort2
v: 0 2 1 7 2 4 0 7 5 8 
After sort: 0 0 1 2 2 4 5 7 7 8 
root@linux_ever:~/linux_ever/algorithm/ch7# ./quicksort2
v: 9 2 1 1 7 9 1 8 8 9 
After sort: 1 1 1 2 7 8 8 9 9 9 
root@linux_ever:~/linux_ever/algorithm/ch7# ./quicksort2
v: 7 1 6 0 6 0 5 3 8 3 
After sort: 0 0 1 3 3 5 6 6 7 8 
root@linux_ever:~/linux_ever/algorithm/ch7# ./quicksort2
v: 7 1 6 0 6 0 5 3 8 3 
After sort: 0 0 1 3 3 5 6 6 7 8 

相關文章