演算法導論-歸併排序
阿新 • • 發佈:2019-01-02
#include <iostream> #define MAXNUM 100000 using namespace std; int A[]={2,4,5,7,1,2,3,6};//需要被排序的陣列 //int A[]={4,41,52,26,38,57,9,49};//需要被排序的陣列 void printA() { for(int i = 0;i<sizeof(A)/ sizeof(int);i++) { cout<<A[i]<<" "; } cout<<endl; } void Merge(int beg,int mid,int end)//該歸併排序將會加入哨兵,避免檢查有一個數組已排序完畢。 { int n1 = mid-beg+1;//左邊需要排序的數的個數 int n2 = end-mid;//右邊需要排序的數的個數 int* A_L = new int[n1+1];//增加一個1用來存放哨兵 int* A_R = new int[n2+1]; for(int i = 0;i<n1;i++) { A_L[i] = A[i+beg]; } for(int i = 0;i<n2;i++) { A_R[i] = A[i+mid+1]; } A_L[n1] = MAXNUM; A_R[n2] = MAXNUM; int i = 0; int j = 0; for(int k = beg;k<=end;k++) { if(A_L[i]<=A_R[j]) { A[k] = A_L[i]; i++; } else { A[k] = A_R[j]; j++; } } delete[] A_L; delete[] A_R; } void Merge_sort(int beg,int end)//beg為開始排序的位置,end為排序的最後一個元素的位置 { if(beg>=end) return ;//當只有一個元素的時候不需要排序 int mid = (beg+end)/2; Merge_sort(beg,mid);//分別對左邊和右邊排序,排序的目標是陣列A Merge_sort(mid+1,end); Merge(beg,mid,end);//將排好序的左邊和右邊的陣列進行合併 } int main() { Merge_sort(0, sizeof(A)/ sizeof(int)-1); printA(); }
遞迴過程:
注意點:
在歸併時,程式加入哨兵,這樣就不用判斷歸併的堆是否為空。歸併結束的條件是被歸併的元素個數是希望被排序的陣列長度。
陣列 {7,5,4,2,6,3,2,1} 的排序過程是
5 7 4 2 6 3 2 1
5 7 2 4 6 3 2 1
2 4 5 7 6 3 2 1
2 4 5 7 3 6 2 1
2 4 5 7 3 6 1 2
2 4 5 7 1 2 3 6
1 2 2 3 4 5 6 7
不加哨兵方法:
#include <iostream> using namespace std; int A[]={7,5,4,2,6,3,2,1};//需要被排序的陣列 //int A[]={4,41,52,26,38,57,9,49};//需要被排序的陣列 void printA() { for(int i = 0;i<sizeof(A)/ sizeof(int);i++) { cout<<A[i]<<" "; } cout<<endl; } void Merge(int beg,int mid,int end)//該歸併排序將會加入哨兵,避免檢查有一個數組已排序完畢。 { int n1 = mid-beg+1;//左邊需要排序的數的個數 int n2 = end-mid;//右邊需要排序的數的個數 int* A_L = new int[n1];//增加一個1用來存放哨兵 int* A_R = new int[n2]; for(int i = 0;i<n1;i++) { A_L[i] = A[i+beg]; } for(int i = 0;i<n2;i++) { A_R[i] = A[i+mid+1]; } int i = 0; int j = 0; int k = beg; while(i<n1 && j<n2) { if(A_L[i]<=A_R[j]) { A[k++] = A_L[i]; i++; } else { A[k++] = A_R[j]; j++; } } if(i!=n1) { while(i<n1) { A[k++] = A_L[i++]; } } else if(j!=n2) { while(j<n2) { A[k++] = A_R[j++]; } } delete[] A_L; delete[] A_R; } void Merge_sort(int beg,int end)//beg為開始排序的位置,end為排序的最後一個元素的位置 { if(beg>=end) return ;//當只有一個元素的時候不需要排序 int mid = (beg+end)/2; Merge_sort(beg,mid);//分別對左邊和右邊排序,排序的目標是陣列A Merge_sort(mid+1,end); Merge(beg,mid,end);//將排好序的左邊和右邊的陣列進行合併 } int main() { Merge_sort(0, sizeof(A)/ sizeof(int)-1); printA(); }