一、什麼是歸併排序?
歸併排序的特點體現在 “歸併” 上,“歸併” 就是“合併”!將兩個或兩個以上有序的序列合併爲一個有序的序列。而2路歸併就是將兩個有序序列合併爲一個有序序列。
二、一個2路歸併排序的圖例:
三、由上圖得出歸併排序思路:
<1>、怎樣合併兩個有序序列(在後面程序中給出)
<2>、實現歸併算法:將r1[ ] 中的元素用歸併法排序後放到 r3[ ]中,使用一個輔助數組r2[ ] ,它的大小由參數給出(詳情看代碼)。
採用遞歸方式進行歸併排序:
a、首先將r1[ ]前半部分的元素用歸併法排序後放到輔助數組r2[ ]的前半部分中。
b、將r1[ ]後半部分的記錄用歸併法排序放到輔助數組r2[ ]的後半部分。
c、將輔助數組r2[ ]的前半部分和後半部分合併到r3[ ]中。
舉例:
四、源代碼實現:
/*
**函數功能: 將有序序列record1[low..mid] 和 有序序列record1[mid+1..high]合併爲一個有序序列record2[low..high]
**參數說明: @record1 :有序序列1
** @low : 序列1的起始下標
** @mid : 序列1的終止下標,mid+1對應序列2的起始下標
** @high: 序列2的終止下標
** @record2 :有序序列2
**返回值 : 無
*/
void Merge(int record1[], int low, int mid, int high, int record2[])
{
//i作爲record1[low..mid]的循環變量,j作爲record1[mid + 1..high]的循環變量
//k作爲record2[low..high]的循環變量
int i = low, j = mid + 1, k = low;
//開始合併
while ((i <= mid) && (j <= high))
{
if (record1[i] <= record1[j])
{
record2[k] = record1[i];
i++;
}
else
{
record2[k] = record1[j];
j++;
}
k++;
}
while (i <= mid)
{
record2[k] = record1[i];
k++;
i++;
}
while (j <= high)
{
record2[k] = record1[j];
k++;
j++;
}
}
/*
**函數功能: 將之前無序的序列recordBefore排序後放入recordAfter中,即函數執行完之後recordAfter爲有序序列
**參數說明: @recordBefore: 無序序列存放數組
** @low : 無序序列起始下標
** @high: 無序序列終止下標
** @recordAfter : 存儲有序序列的數組
**返回值 : 無
*/
void MSort(int recordBefore[], int low, int high, int recordAfter[])
{
int mid;
//輔助數組空間
int *recordMid = NULL;
//因爲輔助輔助要訪問到最大下標爲high,所以數組長度最小爲high+1
recordMid = (int *)malloc(sizeof(recordBefore[0]) * (high+1));
if (low == high)
{
recordAfter[low] = recordBefore[low];
}
else
{
mid = (low + high) / 2;
//首先將recordBefore的前半部分用歸併法合併爲有序,放入輔助空間recordMid中
MSort(recordBefore, low, mid, recordMid);
//再將recordBefore的後半部分用歸併法合併爲有序,放入輔助空間recordMid中
MSort(recordBefore, mid + 1, high, recordMid);
//最後將recordBefore的前半部分和後半部分通過合併算法,合併爲有序序列放入recordAfter中
Merge(recordMid, low, mid, high, recordAfter);
//釋放輔助空間
free(recordMid);
recordMid = NULL;
}
}
/*
**函數功能: 歸併函數入口
**參數說明:
**@record : 序列數組 @len : 序列長度
**返回值: 無
*/
void MergeSort(int record[], int len)
{
MSort(record, 0, len - 1, record);
}
int main(void)
{
int record[] = { 0,46,55,13,42,94,17,05,70,1,2,3,4,5,6 };
int len = sizeof(record) / sizeof(record[0]);
int i = 0;
printf("歸併排序前: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
MergeSort(record, len);
printf("歸併排序後: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
return 0;
}
五、運行截圖: