常用算法排序(04)—— 归并排序

一、 归并排序的基本思想

归并排序是利用先递归进行分解,将一个规模为 n n 的问题分解成两个规模为 n / 2 n/2 的问题,再不断的继续进行递归分解成最终规模为 1 1 的问题。然后再逐渐的从小规模结果进行合并,最终得到完整的结果。也即分而治之的思想。
其图解如下:原图地址
在这里插入图片描述


二、算法分析

归并排序使用了空间换时间的方式,用一个辅助数组来存储每次排序后的结果,然后再将其复制到原数组对应的位置上,会将原数组中对应位置上 的值覆盖掉。
1、如数组 [4,3,2,1] 的递归子问题为 [4,3] 和 [2,1] 其中先将 [4,3] 的排序结果放在辅助数组 temp 中(temp的大小为原数组 arr 的大小)。然后再将在 temp数组中排好序的结果复制到 arr 数组中的对应位置上,如下图所示。递归这个过程就是归并排序。
在这里插入图片描述
2、第一次递归后的排序结果如下

在这里插入图片描述

三、代码

#include<iostream>
#include<string>
using namespace std;

void Merge(int *arr, int *temp, int left, int mid,int right)
{
	int i = left;  //左边递归数组的指针
	int j = mid + 1; //右边递归数组的指针
	int index = 0;

	while (i <= mid && j<=right)
	{
		if (arr[i] < arr[j])
		{
			temp[index++] = arr[i++];
		}
		else
		{
			temp[index++] = arr[j++];			
		}
	}
	while (i <= mid)
	{
		temp[index++] = arr[i++];
	}
	while (j <= right)
	{
		temp[index++] = arr[j++];
	}

	index = 0;
	while (left <= right)
		arr[left++] = temp[index++];

}

void MergeSort(int *arr, int *temp, int left,int right)
{
	
	if (left < right)
	{
		int mid = left + (right - left) / 2;
		MergeSort(arr, temp, left, mid);   //左边归并排序,使得左子序列有序
		MergeSort(arr, temp, mid + 1, right); //右边归并排序,使得右子序列有序
		Merge(arr, temp, left, mid, right);   //将两个有序子数组合并排序
	}
}

int main()
{
	int arr[] = { 4,3,2,1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	//创建一个长度等于原数组长度的辅助数组,避免递归中频繁开辟空间
	int *temp = new int[len];

	MergeSort(arr,temp, 0, len-1);
	delete[] temp;

	for (int i = 0; i < len; ++i)
		cout << arr[i] << " ";

	cout << endl;

	system("pause");
	return 0;
}

运行结果如下:
在这里插入图片描述

四、复杂度分析

  • 空间复杂度为 O ( n ) O(n)
  • 时间复杂度为 O ( n l o g n ) O(nlogn)

参考资料:
图解排序算法(四)之归并排序
排序算法总结之归并排序

发布了213 篇原创文章 · 获赞 48 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/Jeffxu_lib/article/details/104829361