1. 程式人生 > >二路歸併排序

二路歸併排序

      歸併排序是建立在歸併操作操作上的一種有效的排序演算法。該演算法是採用分治法的一個非常典型的應用。將已有序的子序列合併,得到完整有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為二路歸併。

演算法描述:

  • 把長度為n的輸入序列分為兩個長度為n/2的子序列
  • 對這兩個子序列分別採用歸併排序
  • 將兩個排序好的子序列合併成一個最終的排序序列

程式碼實現:

# include<stdio.h>
# include<stdlib.h>
# include<assert.h>

void Meger(int *arr, int len, int width)
{
	int low1 = 0;
	int high1 = low1 + width - 1;

	int low2 = high1 + 1;
	int high2 = low2 + width - 1 < len - 1 ? low2 + width - 1 : len - 1;

	int *brr = (int *)malloc(sizeof(int)* len);
	assert(brr != NULL);

	int index = 0;
	while (low1 < len)//只要有一個段還沒合併進brr中,迴圈都得執行
	{
		//按順序歸併兩個相鄰的段,退出時,有可能第一個段資料歸併完成,也有可能第二個段資料歸併完成
		while (low1 <= high1 && low2 <= high2)
		{
			if (arr[low1] < arr[low2])
			{
				brr[index++] = arr[low1++];
			}
			else
			{
				brr[index++] = arr[low2++];
			}
		}
		while (low1 <= high1)
		{
			brr[index++] = arr[low1++];
		}
		while (low2 <= high2)
		{
			brr[index++] = arr[low2++];
		}
		low1 = high2 + 1;
		high1 = low1 + width - 1 < len - 1 ? low1 + width - 1 : len - 1;

		low2 = high1 + 1;
		high2 = low2 + width - 1 < len - 1 ? low2 + width - 1 : len - 1;
	}
	for (int i = 0; i < len; ++i)
	{
		arr[i] = brr[i];
	}
	free(brr);
}
void MegerSort(int *arr, int len)
{
	for (int i = 1; i < len; i *= 2)
	{
		Meger(arr, len, i);
	}
}
void Show(int *arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = { 2, 7, 96, 45, 32, 45, 76, 29, 94 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Show(arr, len);
	MegerSort(arr, len);
	Show(arr, len);
	return 0;
}

演算法特性:

時間複雜度 空間複雜度 穩定性
O(nlogn) O(n) 穩定