1. 程式人生 > >《演算法導論》第三版 2.3.1 歸併排序

《演算法導論》第三版 2.3.1 歸併排序

MERGE-SORT(A,p,r)

if p<r
    q = (p+r)/2
    MERGE-SORT(A,p,q)
    MERGE-SORT(A,q+1,r)
    MERGE(A,p,q,r)

歸併排序利用遞迴將一個大陣列不斷的從中間對半分成兩個小的陣列直到陣列中只剩下一個元素,然後通過MERGE函式合併。
MERGE-SORT中A是陣列,p是陣列中需要比較的第一個元素的下標,r是最後一個元素的下標。

if p<r

就是用來判斷,陣列區間長度是否大於1,否則直接返回

MERGE-SORT(A,p,q)

q是區間中間元素的下標,將分開後的區間右邊部分用MERGE-SORT函式處理(也就是繼續分割為兩半,直到區間只剩下一個元素)。下一個語句是處理左半邊。
當這兩個函式返回後,由他們處理的區間都已經按順序排列

(只有一個元素的數列當然是已經排好序的),MERGE函式做的只是間這兩個區間合併。

MERGE(A,p,q,r)

n1=q-p+1
n2=r-q
let L[1...n1+1] and R[1..n2+1] be new arrays
for i=1 to n1
    L[i]=A[p+i-1]
for j=1 to n2
    R[j]=A[q+j]
L[n1+1]=
R[n2+1]=
i=1
j=1
for k=p to r
    if L[i]<=R[j]
        A[k]=L[i]
        i=i+1
    else
        A[k
]=R[j] j=j+1

n1是左邊的最後一個元素的下標,n2是右邊最後一個元素的下標,將左右兩邊的元素分別賦值給LR,在最後設定一個無窮大的值,這樣當LR其中一個數組的元素已經全部插入完畢後(實際程式碼中可以通過判斷ij的值來判斷),就只會插入剩下那個陣列中的元素。

i=1
j=1
for k=p to r
    if L[i]<=R[j]
        A[k]=L[i]
        i=i+1
    else
        A[k]=R[j]
        j=j+1

上述程式碼就是插入的過程,將LR的值按從小到大的順序重新放入到陣列A

相應的區間中。

這個遞迴順序是先一直往左到開頭,然後逐步往右

下面給一個例子方便理解:

A: 5 2 4 7 1 3 2 6

MERGE-SORT(左邊) 5   2   4   7MERGE-SORT(左邊) 5   2MERGE-SORT(左邊) 5MERGE-SORT(左邊) p>=r 返回
        →MERGE-SORT(右邊) 2MERGE-SORT(左邊) p>=r 返回
        →MERGE 2 5//A:2 5 4 7 1 3 2 6MERGE-SORT(右邊) 4   7MERGE-SORT(左邊) 4MERGE-SORT(左邊) p>=r 返回
        →MERGE-SORT(右邊) 7MERGE-SORT(左邊) p>=r 返回
        →MERGE 4 7//A:2 5 4 7 1 3 2 6 返回
    →MERGE 2 4 5 7//A:2 4 5 7 1 3 2 6 返回
→MERGE-SORT(右邊) 1   3   2   6MERGE-SORT(左邊) 1   3MERGE-SORT(左邊) 1MERGE-SORT(左邊) p>=r 返回
        →MERGE-SORT(右邊) 3MERGE-SORT(左邊) p>=r 返回
        →MERGE 1 3//A:2 5 4 7 1 3 2 6 返回
    →MERGE-SORT(右邊) 2   6MERGE-SORT(左邊) 2MERGE-SORT(左邊) p>=r 返回
        →MERGE-SORT(右邊) 6MERGE-SORT(左邊) p>=r 返回
        →MERGE 2 6//A:2 5 4 7 1 3 2 6 返回
    →MERGE 1 2 3 6//A:2 5 4 7 1 2 3 6 返回
→MERGE 1 2 2 3 4 5 6 7//A:1 2 2 3 4 5 6 7 返回

下面的都是我自己寫的不是標準答案!!!

1.說明歸併排序在陣列A=<3,41,52,26,38,57,9,49>上的操作

自己做的,隨便看看

2.重寫過程MERGE,使之不使用無窮,而是一旦陣列L或R的所有元素均被複制回A就立即停止,然後把另一個數組的剩餘部分複製回A
n1=q-p+1
n2=r-q
let L[1...n1+1] and R[1..n2+1] be new arrays
for i=1 to n1
    L[i]=A[p+i-1]
for j=1 to n2
    R[j]=A[q+j]
i=1
j=1
for k=p to r
    if L[i]<=R[j]
        A[k]=L[i]
        i=i+1
    else
        A[k]=R[j]
        j=j+1
    if i == n1+1 or j == n2+1
        break
if i<n1+1
    for k to r
        A[k]=L[i]
        i=i+1
else
    for k to r
    A[k]=R[j]
    j=j+1