二路歸並排序主要運用了“分治算法”,分治算法就是將一個大的問題划分為n個規模較小而結構相似的子問題。
這些子問題解決的方法都是類似的,解決掉這些小的問題之后,歸並子問題的結果,就得到了“大”問題的解。
二路歸並排序主旨是“分解”與“歸並”
分解:
1.將一個數組分成兩個數組,分別對兩個數組進行排序。
2.循環第一步,直到划分出來的“小數組”只包含一個元素,只有一個元素的數組默認為已經排好序。
歸並:
1.將兩個有序的數組合並到一個大的數組中。
2.從最小的只包含一個元素的數組開始兩兩合並。此時,合並好的數組也是有序的。

圖1. 歸並排序過程 圖2. 合並兩個有序數組
舉例說明:
1.圖中原始數組為{2,4,7,5,8,1,3,6},數組中元素的個數為8個。首先將8個元素的數組二分,每次分解后,
數組中元素的數目為原數組的一半。直到分解為只含有一個元素的數組。
2.將小的數組按序合並,每次合並后數組的大小為上層數組的一倍。此時數組中的元素都是按序排列的。
3.在合並兩個有序數組。如圖2
下面的是自頂向下遞歸實現2路歸並排序:
#include <iostream>
using namespace std;
void Merge(int * a, int low, int mid, int high)
{
int i = low, j = mid + 1, p = 0;//對應a數組的下標
int * r = new int[high - low + 1];//申請另一個對應大小的數組來存放排好序的數據
while (i <= mid && j <= high)
{
r[p++] = (a[i] <= a[j]) ? a[i++] : a[j++];
}
while (i <= mid)
r[p++] = a[i++];
while (j <= high)
r[p++] = a[j++];
for (p = 0, i = low; i <= high; p++, i++)
a[i] = r[p];//最后再把有序數據存進a數組中,使得a數組對應部分數據有序
delete[] r;
}
//自頂向下(遞歸實現)
void MSort(int *a, int low, int high)
{
if (low<high)
{
int mid = (low + high) / 2;
MSort(a, low, mid);
MSort(a, mid + 1, high);
Merge(a, low, mid, high);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[] = { 2,4,7,5,8,1,3,6 };
int n = sizeof(a) / sizeof(int);
MSort(a, 0, n - 1);
for (int i = 0; i<n; i++)
cout << a[i] << " ";
cout << endl;
system("PAUSE");
return 0;
}
參考資料:《算法導論》2.1章節
