排序算法(七) 2路歸併排序

一、什麼是歸併排序?

       歸併排序的特點體現在 “歸併” 上,“歸併” 就是“合併”!將兩個或兩個以上有序的序列合併爲一個有序的序列。而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;
}

五、運行截圖:

                                     


發佈了51 篇原創文章 · 獲贊 55 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章