1. 程式人生 > >關於分治法歸併排序的個人筆記

關於分治法歸併排序的個人筆記

一.分治法
1. 定義 將原問題分解成兩個或者更多的相似的子問題,再用同樣的方法分解子問題,直到子問題可以輕鬆求解,原問題的解就是子問題解的集合。
2.步驟 分解:分解原問題為若干個子問題。
解決:求解子問題,遞迴的求解子問題。
歸併:子問題的解的集合就是原問題的解。
二.歸併排序
1. 演算法思想:遵循分治法思想,首先分解原問題,將待排序的n個元素的序列分解成兩個具有n/2個元素的子序列。然後使用歸併並排序遞迴地排序兩個子序列。最後合併兩個已經排序的子序列得到已排序的原問題的解。
2. 演算法過程:歸併排序中的關鍵步驟在於合併兩個已排序的序列,我們需要呼叫一個輔助過程MERGE(A,p,q,r)來完成合並過程,其中A表示陣列,p、q、r都是陣列下標,其中A[p…q]和A[q+1…r]代表已排序的兩個序列。
關於MERGE(A,p,q,r)函式的虛擬碼如下:

    MERGE(A,p,q,r)
    1.  n1=q-p+1;
    2.  n2=r-q;
    3.  int B[1...n1+1],C[1...n2+1];//定義兩個輔助陣列
    4. for i=1 to n1  do
    5.    B[i]=A[i+p-1];
    6. for j=1 to n2  do
    7.    C[j]=A[j+q];
    8. B[n1+1]=∞,C[n2+1]=∞;//哨兵作用
    9. i=1,j=1;
    10. for k=p to r
    11.    if(B[i]>C[j])
    12.
A[k]=C[j]; 13. j++; 14. else 15. A[k]=B[i]; 16. i++;

然後是歸併排序的虛擬碼:

MERGE-SORT(A,p,r)
1.if p<r
2.   q=(p+q)/2;
3.   MERGE-SORT(A,p,q);
4.   MERGE-SORT(A,q+1,r);
5.   MERGE(A,p,q,r);

測試:

#include <iostream>
#define INF 10000000

using namespace std
; void Merge(int *A,int p,int q,int r) { int n1=q-p+1; int n2=r-q; int* B = new int[n1+1]; int* C = new int[n2+1]; for(int i=0;i<n1;i++) { B[i]=A[i+p]; } for(int i=0;i<n2;i++) { C[i]=A[i+q+1]; } B[n1]=INF; C[n2]=INF; int i=0,j=0; for(int k=p;k<=r;k++) { if(B[i]>C[j]) { A[k]=C[j]; j++; } else { A[k]=B[i]; i++; } } } void Merge_Sort(int* A,int p,int r) { if(p<r){ int q=(p+r)/2; Merge_Sort(A,p,q); Merge_Sort(A,q+1,r); Merge(A,p,q,r); } } int main() { int A[5]={1,4,7,2,5}; Merge_Sort(A,0,4); for(int i=0;i<5;i++) { cout<<A[i]<<endl; } return 0; }

時間複雜度:O(nlogn)