归并排序

基本思想

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略

分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之。

动画演示

归并动画示例

C++代码

//治阶段:排序并合并分阶段拆分的序列
void merge(vector<int>& v1, vector<int>& v2, int left, int mid, int right)
{
	int i = left;		//左序列起始位置
	int j = mid + 1;	//右序列起始位置
	int begin = left;	//排序数组的起始位置
	//当前分阶段序列排序放入排序后数组v2
	while (i <= mid && j <= right)
	{
		if (v1[i] <= v1[j])
		{
			v2[begin++] = v1[i++];
		}
		else

		{
			v2[begin++] = v1[j++];
		}
	}
	//当前分阶段左右序列长度不等的情况
	//左序列长,则上面循环过后i还小于等于mid, 则将左序列剩余元素移至排序数组后面
	//因为左序列有序且上面已和右序列排序,所以左序列剩余的元素一定大于右序列的,因此可以直接移至排序数组
	while (i <= mid)
	{
		v2[begin++] = v1[i++];
	}
	//右序列长,同理
	while (j <= right)
	{
		v2[begin++] = v1[j++];
	}

	//将当前分阶段的区间的排序后的序列放入原数组
	for (int t = left; t <= right; t++)
	{
		v1[t] = v2[t];
	}

}

//v1:给定待排序数组
//v2:存放排序后序列的数组
//left:指定v1的左边界
//right:指定v1的右边界
void mergeSort(vector<int>& v1, vector<int>& v2, int left, int right)
{
	if (left < right)	//递归终止条件
	{
		int mid = left + (right - left) / 2;	//+left 是为了防止溢出
		//分阶段:将[left, right]区间的序列等分成左右两个子序列,直至left == right为止,即拆分到左右序列均只有一个元素为止。
		mergeSort(v1, v2, left, mid);
		mergeSort(v1, v2, mid + 1, right);
		//治阶段
		merge(v1, v2, left, mid, right);
	}
}

时间复杂度

假设待排序的数组元素个数为n,设高度为x,x意味着该数组中的n个元素需要连续二分x次才剩下1个元素,即n/2^x=1,x=log2n,每一层的总比较次数为n,所以时间复杂度为O(nlogn)

空间复杂度

归并的空间复杂度就是那个临时的数组(我们通过参数传递来取代了临时创建,相当于每次递归调用时将数组大小n也压入栈中了)和递归时压入栈的数据占用的空间:n + logn,所以空间复杂度为: O(n)。

算法稳定性

因为交换元素时,可以在相等的情况下做出不移动的限制,所以归并排序是稳定的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值