大牛的排序算法收集

http://my.oschina.net/plumsoft/blog?catalog=154864

b1.gif 堆排序

0人收藏此文章, 我要收藏發表於4個月前(2013-06-13 13:18) , 已有 52次閱讀 ,共 0個評論

1 排序思想:算法

將排序表的n個記錄按照關鍵字建成堆,堆頂元素就是選擇出的最大(或最小)記錄,這樣就獲得排序的第一個記錄。再將剩下的n-1個記錄建成堆,獲得次大(或者次小)的記錄。如此反覆,直到執行n-1次後,排序結束。shell

大頂堆的性質:R[i]>=R[2i]且R[i]>=R[2i+1]數組

2 算法實現:ide

// 堆排序
void heap_sort(int num[], int n){
    int i;
    // 將num[]調整成大頂堆
    // 即num[i]>=num[2i]&&num[i]>=num[2i+1]
    for(i=n/2;i>=0;i--){
        heap_adjust(num,i,n);
    }
    for(i=n-1;i>0;i--){
        // 將每一輪的堆頂放在i
        SWAP(num[0],num[i]);
        // 再將剩下的i個記錄調整成大頂堆
        heap_adjust(num,0,i);
    }
}
// 將num[s,q)段調整成大頂堆
// num[s]>=num[2s]且num[s]>=num[2s+1]
void heap_adjust(int num[],int s,int q){
    int rc=num[s];
    int i;
    for(i=2*s;i<q;i*=2){
        if(i<q-1&&num[i]<num[i+1])
            i++;
        if(rc>=num[i])
            break; // rc應當放在位置s
        num[s]=num[i];
        s=i;
    }
    num[s]=rc;
}
#define SWAP(x,y) {int t; t = x; x = y; y = t;}

3 性能分析:性能

3.1 空間複雜度:O(1)ui

3.2 時間複雜度:平均和最壞時間複雜度是O(nlogn)spa

3.3 穩定性:不穩定.net


b1.gif 快速排序

0人收藏此文章, 我要收藏發表於5個月前(2013-06-11 19:12) , 已有 58次閱讀 ,共 0個評論

1 排序思想:blog

經過一趟排序,將待排序記錄分紅兩個部分,其中一部分的關鍵字都比另外一部分的關鍵字小。再分別對這兩部分進行排序,直到整個序列有序。排序

以整型數組爲例,一趟快速排序的方法:

待排序序列爲R[low...high],取一個基準,通常爲R[low]

設i=low,j=high-1

①從j向前搜索,直到j<=i或者R[j]< R[low],將R[j]與R[i]交換
②從i向後搜索,直到j<=i或者R[i]> R[low],將R[i]與R[j]交換
重複①、②步,直到j<=i,這樣完成一趟排序,i就是最終基準所放置的位置

2 算法實現:

// 對num[]的[low,high)段執行快速排序
void quick_sort(int num[],int low,int high){
    if(low<high){
        int pivotloc=partion(num,low,high);
        quick_sort(num,low,pivotloc);
        quick_sort(num,pivotloc+1,high);
    }
}
// 對num[]的[low,high)段,按照num[low]分割成兩部分
// 並返回最終num[low]所放置位置
int partion(int num[],int low,int high){
    int i=low,j=high-1;
    int key=num[low];
    while(i<j){
        while(i<j&&key<=num[j]) j--;
        SWAP(num[i],num[j]);
        while(i<j&&key>=num[i]) i++;
        SWAP(num[i],num[j]);
    }
    return i;
}
// 交換
#define SWAP(x,y) {int t; t = x; x = y; y = t;}

3 性能分析:

3.1 空間複雜度:在理想狀態下是O(logn),最壞狀況下是O(n)

3.2 時間複雜度:

最好狀況:一趟排序須要對記錄進行比較約n次,則總的時間複雜度要看執行劃分的次數。理想狀況下,每次劃分都將序列分紅兩個等長的部分,則時間複雜度是O(nlogn)。最壞狀況下,每次劃分都只將序列分紅一部分,時間複雜度是O(n^2)。

平均時間複雜度是O(nlogn)

當序列已是正序,快速排序退化爲冒泡排序。

3.3 穩定性:不穩定


b1.gif 希爾排序

0人收藏此文章, 我要收藏發表於5個月前(2013-06-11 13:43) , 已有 35次閱讀 ,共 0個評論

1 排序思想:

第1趟:取一正整數d1(d1<n)做爲第一個增量,對全部間隔爲d1的記錄進行直接插入排序。例如,對{a[k],a[k+d1],a[k+2d1],……}執行直接插入排序,其中,k=0,1,2,……,d1-1
第2趟:取一正整數d2(d2<d1),重複上一步的操做
直到所取的增量爲1

例如,原始數據:

134045_H7rc_164134.png

第1趟排序,取增量爲5,如上圖,顏色相同的在同一組,對每組進行直接插入排序:

134104_EmwA_164134.png

第2趟排序,取增量爲3,如上圖,顏色相同的在同一組,對每組進行直接插入排序:

134125_hbRh_164134.png

第3趟排序,取增量爲1,即對上一步的結果進行直接插入排序:

134138_XpHU_164134.png

2 算法實現:

// 根據增量序列dk[]對num[]進行希爾排序
void shell_sort(int num[],int num_len,int dk[],int dk_len){
    int k;
    for(k=0;k<dk_len;k++)
        shell_pass(num,num_len,dk[k]);
}
// 根據增量d對num[]進行一次希爾排序
// 即對全部間隔爲d的記錄進行直接插入排序
void shell_pass(int num[],int num_len,int d){
    int i,j,k,key;
    for(i=d;i<num_len;i++){
        // 將num[i]插入到指定位置
        key=num[i];
        j=i-d;
        while(j>=0&&num[j]>key){
            num[j+d]=num[j];
            j-=d;
        }
        num[j+d]=key;
    }
}

3 性能分析:

3.1 空間複雜度:如上代碼,僅在交換數據時使用一個輔助空間,空間複雜度是O(1)

3.2 時間複雜度:O(nlogn)-O(n^2)

3.3 穩定性:不穩定


b1.gif 簡單選擇排序

0人收藏此文章, 我要收藏發表於5個月前(2013-06-10 16:36) , 已有 25次閱讀 ,共 0個評論

1 排序思想:

第1趟:從第0個到第(n-1)個記錄中選擇關鍵字最小的記錄,與第0個記錄交換
第2趟:從第1個到第(n-1)個記錄中選擇關鍵字最小的記錄,與第1個記錄交換
……
第i趟:從第(i-1)和到第(n-1)個記錄中選擇關鍵字最小的記錄,與第(i-1)個記錄交換
……
直到第(n-1)趟,在最後兩個記錄中選擇關鍵字最小的,與第(n-2)個記錄交換

2 算法實現:

// 選擇排序
void select_sort(int num[], int n){
    int i,j,min_index,tmp;
    // 要進行n-1趟排序
    for(i=0;i<n-1;i++){
        // min_index爲這一趟關鍵字最小的記錄的下標
        min_index=i;
        // 從num[j,n-1]中找到關鍵字最小的
        for(j=i+1;j<n;j++){
            if(num[min_index]>num[j])
                min_index=j;
        }
        // 交換
        if(min_index!=i){
            tmp=num[min_index];
            num[min_index]=num[i];
            num[i]=tmp;
        }
    }
}

3 性能分析:

3.1 空間複雜度:如上代碼,僅在交換數據時使用一個輔助空間,空間複雜度是O(1)

3.2 時間複雜度:不論原始記錄如何,每一趟要進行的比較操做都是肯定的。以上面代碼爲例,第i趟排序,須要比較(n-i-1)次(從i+1到n-1),整個排序過程的比較次數爲

163517_fDJY_164134.gif

記錄移動的次數,最小是0次,最可能是3(n-1)次。

於是簡單排序算法的最好、最差和平均時間複雜度都是O(n^2)

3.3 穩定性:關於簡單排序的穩定性,有必定的爭議,通常認爲是不穩定的。可是上面的代碼,明顯是穩定的。要是遇到筆試題,仍是選擇不穩定吧。


b1.gif 歸併排序

1人收藏此文章, 我要收藏發表於5個月前(2013-06-09 10:24) , 已有 74次閱讀 ,共 2個評論

1 排序思想:

將待排序表R一、R二、R三、……、R(n)當作是n個長度爲1的有序子表,對相鄰的兩個有序子表兩兩合併,獲得每兩個元素有序的表;再將長度爲2的有序子表兩兩合併,獲得每四個元素有序的表;直到獲得一個長度爲n的有序表。排序過程以下:

原始數據:

104258_3Cwq_164134.png

第1趟排序後:

104304_ERKt_164134.png

第2趟排序後:

104315_2r0f_164134.png

第3趟排序後:

104323_EumX_164134.png

第4趟排序後:

104329_cPo8_164134.png

2 算法實現:

// 歸併排序
void merge_sort(int num[], int p, int r){
    if(r-p>1){
        int q=(p+r)/2;
        merge_sort(num, p, q);
        merge_sort(num, q, r);
        merge(num, p, q, r);
    }
}
// 將兩個列表歸併的過程,這裏表示將
// 列表num[]的num[p,q-1]和num[q,r-1]兩段有序子表歸併
void merge(int num[], int p, int q, int r){
    int n1=q-p;
    int n2=r-q;
    // 建立兩個列表,分別存儲num[p,q-1]和num[q,r-1]
    int *left=new int[n1];
    int *right=new int[n2];
    int i,j,k;
    // 列表賦值
    for(i=0;i<n1;i++)
        left[i]=num[p+i];
    for(j=0;j<n2;j++)
        right[j]=num[q+j];
    i=0;
    j=0;
    // 將兩個列表left和right的內容按順序放在num[p,r-1]
    for(k=p;k<r;k++){
        if(i<n1&&left[i]<=right[j]){
            num[k]=left[i];
            i++;
        }
        else if(j<n2){
            num[k]=right[j];
            j++;
        }
    }
    delete []left;
    delete []right;
}

3 性能分析:

3.1 空間複雜度:如上代碼,每一輪的歸併操做使用的輔助元素數組空間長度與原始表等長,爲n,而每一輪歸併以後,這些輔助空間均可以釋放掉,所以空間複雜度是O(n)

3.2 時間複雜度:

對於歸併排序,不論原始列表排序狀況如何,時間複雜度都是同樣的。由於每一輪要進行的比較次數爲n,賦值操做次數爲2n

要進行logn輪歸併操做,則時間複雜度是O(nlogn)

3.3 穩定性:穩定


b1.gif 冒泡排序

0人收藏此文章, 我要收藏發表於5個月前(2013-06-08 16:33) , 已有 63次閱讀 ,共 0個評論

1 排序思想:

依次比較相鄰的兩個元素,若逆序,則交換位置。直到沒有反序的記錄。

第1趟:依次比較並交換R1與R二、R2與R三、……、R(n-1)與R(n),此次排序以後,第n個記錄就是最終記錄;
第2趟:對前(n-1)個記錄進行上述操做,則第(n-1)個記錄就在其最終位置;
而後依次對前(n-2)、前(n-3)、……、前2個記錄進行上述操做。共需(n-1)趟排序。
若是某一趟沒有進行交換記錄,則說明已經完成排序,應當中止排序。

冒泡排序每趟排序操做均可以將一個元素放到最終位置。

2 算法實現:

// 冒泡排序
void bubble_sort(int num[], int len){
    int i,j,tmp;
    bool flag;
    // 共需進行len-1趟排序
    for(j=0;j<len-1;j++){
        flag=true;
        // 每趟排序對前len-j個元素進行處理
        for(i=0;i<len-j-1;i++){
            if(num[i]>num[i+1]){
                tmp=num[i];
                num[i]=num[i+1];
                num[i+1]=tmp;
                flag=false;
            }
        }
        // 若是flag等於true,表示這一趟沒有進行交換
        // 即前len-j個元素是有序的,能夠中止比較
        if(flag)
            break;
    }
}

3 性能分析:

3.1 空間複雜度:如上代碼,使用了一個輔助單元tmp,空間複雜度爲O(1)

3.2 時間複雜度:

3.2.1 最好狀況:待排序記錄已是有序的,則只要進行一趟排序,關鍵字比較(n-1)次,記錄移動0次。

時間複雜度O(n)

3.2.2 最壞狀況:待排序記錄已是逆序的,則一趟排序,關鍵字比較次數(n-i-1)次,記錄移動3(n-i-1)次。整個過程

比較次數爲

163202_oSD7_164134.gif

記錄移動次數爲

162138_22zV_164134.gif

時間複雜度O(n^2)

3.2.3 平均時間複雜度:O(n^2)

3.3 穩定性:穩定


b1.gif 折半插入排序

2人收藏此文章, 我要收藏發表於1年前(2012-03-28 23:33) , 已有 480次閱讀 ,共 0個評論

1 排序思想:

直接排序的基礎上,將待排序的記錄Ri插入到已經排好序的記錄R1,R2,……,R(N-1)中,因爲記錄R1,R2,……,R(N-1)已經排好序,因此在查找插入位置時可採用「折半查找」。

2 算法實現:

// 折半插入排序
void binary_insert_sort(int num[], int len){
    int i,j,key,low,high,mid;
    for(i=1;i<len;i++){
        key=num[i];
        low=0;
        high=i-1;
        mid=(low+high)/2;
        // 尋找插入點,最終插入點在low
        while(low<=high){
            if(key<num[mid])
                high=mid-1;
            else 
                low=mid+1;
            mid=(low+high)/2;
        }
        // 移動記錄
        for(j=i;j>low;j--){
            num[j]=num[j-1];
        }
        // 插入記錄
        num[low]=key;
    }
}

3 性能分析:

3.1 空間複雜度:如上代碼,使用了一個輔助單元key,空間複雜度爲O(1)

3.2 時間複雜度:雖然折半查找減小了記錄比較次數,但沒有減小移動次數,所以時間複雜度同直接查找算法。

3.2.1 最好狀況:時間複雜度O(n)

3.2.2 最壞狀況:時間複雜度O(n^2)

3.2.3 平均時間複雜度:O(n^2)

3.3 穩定性:穩定


b1.gif 直接插入排序

2人收藏此文章, 我要收藏發表於1年前(2012-03-26 20:49) , 已有 479次閱讀 ,共 1個評論

1 排序思想:

將待排序的記錄Ri插入到已經排好序的記錄R1,R2,……,R(N-1)中。

對於一個隨機序列而言,就是從第二個元素開始,依次將這個元素插入到它以前的元素中的相應位置。它以前的元素已經排好序。

第1次排序:將第2個元素插入到前邊的有序列表(此時前邊只有一個元素,固然是有序的),以後,這個序列的前2個元素就是有序的了。
第2次排序:將第3個元素插入到前邊長度爲2的有序列表,使得前2個元素是有序的。
以此類推,直到將第N個元素插入到前面長度爲(N-1)的有序列表中。

2 算法實現:

// 直接插入排序
void straight_insert_sort(int num[], int len){
    int i,j,key;
    for(j=1;j<len;j++){
        key=num[j];
        i=j-1;
        while(i>=0&&num[i]>key){
            num[i+1]=num[i];
            i--;
        }
        num[i+1]=key;
    }
}

3 性能分析:

3.1 空間複雜度:如上代碼,使用了一個輔助單元key,空間複雜度爲O(1)

3.2 時間複雜度:

3.2.1 最好狀況:待排序記錄已是有序的,則一趟排序,關鍵字比較1次,記錄移動2次。則整個過程

比較次數爲

143428_lnfu_164134.gif

記錄移動次數爲

143459_QulX_164134.gif

時間複雜度O(n)

3.2.2 最壞狀況:待排序記錄已是逆序的,則一趟排序,關鍵字比較次數i次(從i-1到0),記錄移動(i+2)次。整個過程

比較次數爲

143538_OnW7_164134.gif

記錄移動次數爲

143610_1BYa_164134.gif

時間複雜度O(n^2)

3.2.3 平均時間複雜度:O(n^2)

3.3 穩定性:穩定

相關文章
相關標籤/搜索