算法導論學習筆記(2)-歸併排序

今天學習了算法導論上的歸併排序算法,並且完成了在紙上寫出僞代碼,以前就學過歸併但是理解的不夠透徹,

前還一直困惑:爲什麼明明歸併排序比快排的時間複雜度更穩定,爲什麼庫函數不用歸併而用快排,現在知道原因了,因爲歸併排序必須開額外的空間,而且空間開銷還比較大,下面介紹算法:

首先,歸併排序用到了分治的思想,把大數據分成若干個小數據,然後再分別對小數據進行處理,最後把小數據

合併成大數據。

其次,歸併排序用到了一個最重要的特點,就是把兩組已經排序的數據合併成一組有序數據,並且該過程的時間復

雜度爲O(n)。

最後,算法便出來了,對於一個數組A[n]來說,我們要對他進行排序,首先,我們假設A[0~n/2]和A[n/2+1,n-1]爲

有序序列,那麼,我們就可以在O(n)的時間內排好序,可是,問題是,A[0~n/2]和A[n/2+1,n-1]並不是有序序列,於是我們就要將他們都變成有序序列,如何變呢?我們再分別對A[0~n/2]和A[n/2+1,n-1]進行排序即可,對於A[0~n/2]來說,我們運用和以上相同的方法,把他分成A[0~n/2/2]和A[n/2+1,n/2],然後如果這兩個數組均爲有序序列的話,那麼就可以把它們合併起來,然後在返回到上一層了,那麼如何才能判斷他們爲有序呢?當只有一個元素的時候這個元素便是有序的,所以,只需要遞歸到元素個數爲1,然後再返回合併即可。

下面是對以下下代碼中的merge()(合併)函數正確性的證明:

1.當第一次循環迭代的時候,i = L, A[L, i-1]爲空,是有序的序列(空也算有序序列),並且含有i-L=0個LA[n1],RA[n2]的最小的數,這時c1 = c2 = 0, LA[c1]和RA[c2]均爲彼此數組中的最小的元素。

2.假設第i次迭代的時候LA[c1] <= RA[c2], 這時LA[c1]便是還沒有被複制到A中的最小的元素,此時A中含有i-L個最小的元素,當執行A[i] = LA[c1]時,A中便含有i-L+1個最小的元素,然後增加c1和i進行下一次迭代,如果第一次時LA[c1] > RA[c2],執行相似的過程。

3.循環結束後,i = r+1, 此時A中含有i-L = r-L+1個最小的元素,恰好是l~r所有的元素,並且已排好序,證畢。

//insertion_sort
#include <iostream>
using namespace std;
const int inf = (1<<28);

void print(int* A, int n)
{
    for (int i = 0; i < n; i++) {
        cout << A[i] << " ";
    }
    cout << endl;
}
void merge(int *A, int l, int m, int r)
{
    int n1 = m-l+1, n2 = r-m;
    int lA[(const int)(n1+1)], rA[(const int)(n2+1)];
    for (int i = 0; i < n1; i++) {
        lA[i] = A[i+l];
    }
    for (int i = 0; i < n2; i++) {
        rA[i] = A[m+1+i];
    }
    lA[n1] = rA[n2] = inf;
    int c1 = 0, c2 = 0;
    for (int i = l; i <= r; i++)
    {
        if (lA[c1] <= rA[c2]) {
            A[i] = lA[c1++];
        }
        else {
            A[i] = rA[c2++];
        }
    }
}
void merge_sort(int *A, int l, int r)
{
    if (l < r)
    {
        int m = (l + r) / 2;
        merge_sort(A, l, m);
        merge_sort(A, m+1, r);
        merge(A, l, m, r);
    }
}
int main()
{
    int A[10] = {43,2,53,1,8,29,52,4,8,10};
    
    cout << "before sorted: ";
    print(A, 10);
    
    merge_sort(A, 0, 10);
    
    cout << "after sorted: ";
    print(A, 10);
    
    return 0;
}




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