〉〉分解:將原問題分解成一系列子問題
〉〉解決:遞迴地求解各子問題。若子問題足夠小,則直接求解
〉〉合併:將子問題的結果合併成原問題的解。
歸併排序(合併排序)
歸併排序的關鍵在於歸併兩個相鄰的子串行,使其變成乙個排序好的新序列。如果這個新序列就是原來需要進行排序的陣列,那麼排序完成。所以,我們需要將原序列遞迴地分成若干子串行,直道最小的子串行只有乙個元素,然後將子串行依次歸併,就可以得到排序好的原序列。我們要解決的第乙個問題就是:假設有子串行a[p...q]和子串行[q + 1...r]是已經排序好的子串行,如何按順序將它們歸併到乙個子串行中去呢?
歸併兩個子串行
我們可以用撲克牌做模擬。將兩堆數量相近的撲克牌按順序疊好,最小的牌放在最上面,牌面朝上。
〉〉第一步:拿出兩張中較小的一張,放在桌上。
〉〉第二步:分別比較所拿的牌和兩個堆上面的牌,重複第一步,跟在前一張牌的後面。直到乙個堆拿完。
〉〉第三步:將剩餘的堆從上往下一次放在桌上,跟在前一張牌的後面。
由此可見,按問題要求(加橙色的),我們可以設計如下**:
void merge(int ar, int p, int q, int r, int temp)
while(i <= q) //如果ar[p..q]有剩
temp[k++] = ar[i++];
while(j <= r) //如果ar[q+1..r]有剩
temp[k++] = ar[j++];
for(k = 0; k <= (r - p); k++) //將合併後的子串行賦值給原序列ar[p...r]
ar[p + k] = temp[k];
}對於歸併排序,我們要解決的第二個問題就是:原序列如何成為有序序列?
利用分治策略使原序列有序
我們可以通過將原序列二分為兩個子串行,再將兩個子串行二分為另外的四個子串行,直到不能再分解為止。然後分別合併相鄰的兩個子串行,直到不能合併為止。這裡引用網路上的一張圖修改後來說明這個原理。
前面提到過,解決乙個給定問題,演算法需要一次或多次地遞迴呼叫自身來解決相關的子問題,這種演算法通常採用分治策略。所以,我們可以利用分治策略通過通過遞迴呼叫乙個函式來解決。我們可以這樣寫**:
void mergesort(int ar, int head, int end, int temp)
}分析上面的**,我們可以將上圖示上執行順序(建議在新視窗開啟下圖),來驗證該演算法的正確性。同時,你也可以通過類似「迴圈不變式」的方法證明:
完整**
到這裡,歸併排序的所有問題都解決完了。我們給出完整的不帶注釋(分配記憶體後的空注釋是標誌,提醒一定要及時釋放記憶體)的**。
1 #include
2 #include
3 #include
4 #include
5 6 void mergesort(int , int, int, int );
7 void merge(int , int, int, int, int);
8 9 int main(int argc, char * ar**)
23 24 mergesort(ar, 0, n - 1, temp);
25 26 printf("\n歸併排序後:\n");
27 for(i = 0; i < n; i++)
28 printf("%-4d",ar[i]);
29 30 free(temp);
31 free(ar);
32 33 _getch();
34 return 0;
35 }
36 37 void mergesort(int ar, int head, int end, int temp)
44 }
45 46 void merge(int ar, int p, int q, int r, int temp)
54 while(i <= q)
55 temp[k++] = ar[i++];
56 while(j <= r)
57 temp[k++] = ar[j++];
58 59 for(k = 0; k <= (r - p); k++)
60 ar[p + k] = temp[k];
61 }
mergesor
分治法,歸併排序
1.時間複雜度為o nlog n 非降序 package com.cn.insertion 歸併排序,採用分治法的策略 author administrator public class merge sort mergesort a,0,9 for int i 0 i a.length i 先分在和...
分治法(歸併排序)
分治法.cpp 定義控制台應用程式的入口點。include stdafx.h include include include define max 30 using namespace std int l max int r max void merge int a,int p,int q,int ...
分治法 歸併排序
歸併排序是分治法的典型應用,思想如下 divide divide the array to 2 subarray conquer reverse in 2 subarray,if only one elem return combine merge two ordered subarray t n ...