二路歸併 c++實現
阿新 • • 發佈:2020-12-28
二路歸併
- 時間複雜度。CBA(基於比較)的排序演算法的最好的複雜度是o(nlogn),最壞情況o(n^2) 歸併排序的演算法即使在最壞情況下複雜度都是O(nlogn)
- 歸併演算法是分治策略的應用
1)將待排序序列一分為二,時間o(1)
2)對於劃分的子序列,分別遞迴排序 ----分 2o(n/2)
3)當子序列分別有序,合併有序子序列 —治 o(n)
T(n) = 2T(n / 2) + o(n)
這個遞推式的結果可以數學方面計算,最終是o(nlogn)
[4, 8,68, 8, 32, 7, 98] 為例
[4, 8, 68, 8] [32, 7, 98][4, 8][68, 8] [32, 7], [98]
[4], [8],[68], [8], [32], [7], [98] 分到單序列,子序列有序
[4, 8][8, 68] [7,32], [98] 合
[4, 8,8, 68] [7,32, 98] 合
[4, 7, 8,8, 32, 68, 98] 合
-
演算法實現
//有序子序列的合併部分 void merge(int *a, int low, int mid, int high) { int * A = a + low; int lb = mid - low; //只申請一半的空間,防止合併的時候覆蓋 int
圖示
-
精簡實現。因為C在A中,沒有單獨申請空間,所以當B合併完畢的時候,程式就可以結束,C不再拷貝
void merge(int *a, int low, int mid, int high) { int * A = a + low; int lb = mid - low; int * B = new int[lb]; for (int i = 0; i < lb; i++) { B[i] = A[i]; } int lc = high - mid; int * C = a + mid; //精簡實現,因為C在A中,沒有單獨申請空間,所以當B合併完畢的時候,程式就可以結束,C不再拷貝 /*for (int i = 0, j = 0, k = 0; (j < lb || k < lc);) { if ((j < lb) && ((lc <= k) || (B[j] <= C[k]))) { A[i++] = B[j++]; } if ((k < lc) && ((lb <= j) || (C[k] < B[j]))) { A[i++] = C[k++]; } }*/ for (int i = 0, j = 0, k = 0; j < lb;) { //上面已經有j<lb判定可以刪除重複的 if ((lc <= k) || (B[j] <= C[k])) { A[i++] = B[j++]; } //執行完B的合併,不再拷貝C if ((k < lc) && (C[k] < B[j])) { A[i++] = C[k++]; } } }