快速排序算法實現

快速排序算法幾種寫法。
首先快排的思想是選取一個數來劃分數組,這個數左邊的數都小於等於它,右邊的數都大於等於它。就這樣遞歸的劃分數組,最後達到快排的目的。
以下3種方法實現主要區別在於劃分數組操作不一樣,只要數組劃分好了,後面操作都一樣。
// 第一種方法,挖坑填坑方法。先選取數組第一個數作爲參考數,然後分別設置兩個指針i,j。i指向最左端,j指向最右端。首先把數組參考數所在位置挖掉作爲當前坑,此時坑所在位置及指針i指向的位置,然後指針 j 開始遍歷數組,直到遇到小於等於參考數的元素,將其挖出去填當前指針 i 指向的坑,此時更新新的坑,即指針 j 指向的坑,然後指針 i 向前遍歷數組元素,直到找到大於等於參考數的元素,然後將其挖出去填指針j 指向的坑,依次反覆,直到指針i與j相遇爲止,最後把參考數填最後一個坑。這就是一趟排序結果。

#include<iostream>
using namespace std;
void quicksort(int a[], int left, int right){
    int index = a[left];//choose the left data as a index data
    int i = left;  //從左邊開始挖坑,i=left爲第一個坑
    int j = right;//指向排序數的兩個指針
    if (left >= right)  //注意這裏遞歸結束標誌一定是劃分數組沒有元素爲止,只有一個元素返回時不行,因爲有可能越界情況出現
        return ;
    while (i < j){
        while (a[j] > index && i < j)
            --j;//從排序數組的右邊開始遍歷知道找到小於標誌位的數
        if (i < j)
            a[i] = a[j];//第j個位置挖坑,挖出來東西填第i個坑
        while (a[i] <= index && i < j)
            ++i;
        if (i < j)
            a[j] = a[i];// 第i個位置挖出東西填第j個位置坑
    }
    a[j] = index;
    // 上面的實現選取左邊第一個數爲劃分標誌位,標誌位左邊的數都小於它,右邊都大於等於它
    quicksort(a,left,j-1);
    quicksort(a,j+1,right);
}
int main(){
    int a[]={9,2,3,7,4};
    quicksort(a,0,4);
    for (int i = 0; i < 5; ++i)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

第二種參考數歸位方法是從數組左端開始遍歷,選取數組最左端的元素作爲參考數,並把中點指針指向參考數所在位置,(中點指針指的是其左端的數均小於參考數,其自身及其右端的數均大於等於參考數)如果遇到小於參考數的元素,就將其與中點指針指向的元素交換,並將中點指針向前一步,這樣操作下去直到遍歷完數組。

#include<iostream>
using namespace std;
void swap( int *a, int*b){
    int c;
    c=*a;
    *a=*b;
    *b=c;
}
void quicksort(int a[], int left, int right){
    int temp = a[left];// 選取左邊的數爲劃分數組的參考標準數
    int j = left + 1;
    int pivot = left; // pivot中間指針,pivot指針之前的數均小於參考數,pivot之後的數均大於等於參考數。
    if (left < right){
        while (j <= right){
            if ( a[j] < temp){
                swap(&a[j],&a[pivot]);
                ++pivot;
            }
            ++j;
        }
        quicksort(a,left,pivot-1);
        quicksort(a,pivot+1,right);
    }
}

int main(){
    int a[]={9,2,3,7,4};
    quicksort(a,0,4);
    for (int i = 0; i < 5; ++i)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

第一種和第二種方法主要區別就在比較次數不同,第二個相當於逐個冒泡遍歷方法,每次都要需要將大數冒泡到後移,增加交換次數,但是挖坑填洞方法比較次數較少,例如9,3,2,7,4一趟排序的話,第一種只需要交換一次,即4與9交換,一趟下來結構爲4,3,2,7,9;但是用第二種方法的話要把9往後冒泡,則交換4次,一趟結果爲3,2,7,4,9.

第三種方法不用遞歸實現。
未完

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