二路归并排序

基本思想:

二路归并排序主要运用了“分治算法”,分治算法就是将一个大的问题划分为n个规模较小而结构相似的子问题。

二路归并排序主旨是“分解”与“归并”:

1.一直分两组,分别对两个数组进行排序(根据上层对下层在一组的数据通过临时数组排序,再将有序数组挪回上层数组中)。

2. 循环第一步,直到划分出来的“小组”只包含一个元素,只有一个元素的数组默认为已经排好序。

:(合并时,站在上层合并下层(使组内有序))

1.将两个有序的数组合并到一个大的数组中。

2.从最小的只包含一个元素的数组开始两两合并。此时,合并好的数组也是有序的。最后把小组合成一个组。

图解:

二路归并排序_第1张图片

注:此图来自网络,谢谢帮助理解二路归并排序思想

代码实现:

//根据上层对下层在一组的数据通过临时数组排序,再将有序数组挪回上层数组中
void Merge(int arr[], int tmp[],
	int startIndex, int midIndex, int endIndex)
{
	//初始化
	int leftIndex = startIndex;
	int rightIndex = midIndex + 1;
	int tmpIndex = startIndex;
	//									            不越界
	while (leftIndex < midIndex + 1 && rightIndex < endIndex + 1)
	{
		if (arr[leftIndex] > arr[rightIndex])
		{
			tmp[tmpIndex++] = arr[rightIndex++];
		} 
		else
		{
			tmp[tmpIndex++] = arr[leftIndex++];
		}
	} 
	while (leftIndex < midIndex + 1)//当右越界
	{
		tmp[tmpIndex++] = arr[leftIndex++];
	}
	while (rightIndex < endIndex + 1)//当左越界
	{
		tmp[tmpIndex++] = arr[rightIndex++];
	}
	for (int i = startIndex; i < endIndex + 1; ++i)//将临时数组中的有序数据“挪回”原数组
	{
		arr[i] = tmp[i];
	}
}

//将arr[]分组、排序过程
//左分 递归,右分 排序 回溯的过程

void MyMerge(int arr[], int tmp[],
	int startIndex, int endIndex)
{
	if (startIndex < endIndex)
	{
		int midIndex = (endIndex + startIndex) / 2;
		MyMerge(arr, tmp, startIndex, midIndex);//左分
		MyMerge(arr, tmp, midIndex + 1, endIndex);//右分
		Merge(arr,tmp,startIndex,midIndex,endIndex);//排序
	}
} 

void MergeSort(int arr[], int len)
{
	int *tmp = (int*)malloc(sizeof(int)*len);//动态开辟tmp数组
	MyMerge(arr, tmp, 0, len - 1);//将arr[]分组、排序过程
}
void MergeShow(int arr[], int len)
{
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = { 265, 3, 16, 13, 16, 13, 1, 36, 6, 66, 81, 78 };
	int len = sizeof(arr) / sizeof(arr[0]);
	MergeSort(arr, len);
	MergeShow(arr,len);
	return 0;
} 

总结:

时间复杂度:平均O(nlog2n),最好O(nlog2n),最坏O(nlog2n)

空间复杂度:O(n)

稳定

 

你可能感兴趣的:(数据结构)