归并排序

归并排序利用分治法,每次将原序列分为大小基本相等的两个子序列,将两个子序列分别排好序后,再将两个子序列合并为排好序的原序列,而长度大于一的子序列可以递归地分解成更小的子序列,从而递归的用归并排序来解决。因此,递归排序的关键在于如何合并。

简单的归并排序的合并过程是需要借助临时数组的,因此还是比较费空间的。所以如果用对链表组成的序列的排序,归并排序可以不需要额外的空间,这样会更好。

如下是基于数组的序列的归并代码:

void MergeSort(int* pData,int length)
{
	int* pTemp = new int[length];

	DoMergeSort(pData,pTemp,0,length-1);

	delete[] pTemp;
}

void DoMergeSort(int* pData,int* pTemp,int low,int high)
{
	if(low == high)
		return;

	int middle = (low+high) /2 ;
	DoMergeSort(pData,pTemp,low,middle);
	DoMergeSort(pData,pTemp,middle+1,high);

	for(int i=low;i<=high;++i)
		pTemp[i] = pData[i];

	int left = low;
	int right = middle+1;

	for(int i=low;i<=high;++i)
	{
		if(left>middle)
			pData[i] = pTemp[right++];
		else if(right > high)
			pData[i] = pTemp[left++];
		else
		{
			if(pTemp[left] < pTemp[right])
				pData[i] = pTemp[left++];
			else
				pData[i] = pTemp[right++];
		}
	}
}

下面是对上面合并方法的一个简单变种:

void MergeSort2(int* pData,int length)
{
	int* pTemp = new int[length];

	DoMergeSort2(pData,pTemp,0,length-1);

	delete[] pTemp;
}

void DoMergeSort2(int* pData,int* pTemp,int low,int high)
{
	if(low == high)
		return;

	int middle = (low+high) /2 ;
	DoMergeSort(pData,pTemp,low,middle);
	DoMergeSort(pData,pTemp,middle+1,high);

	for(int i=low;i<=middle;++i)
		pTemp[i] = pData[i];
	for(int j=1;j<=high-middle;++j)
		pTemp[high-j+1] = pData[middle+j];

	for(int i=low,left=low,right=high;i<=high;++i)
	{
		if(pTemp[left] < pTemp[right])
			pData[i] = pTemp[left++];
		else
			pData[i] = pTemp[right--];
	}
}

变化之处,就是在从主数组将数据拷贝到临时数组的时候,左边部分是顺序拷贝的,但是右边部分则是倒序拷贝的,最终的结果就是在临时数组中,从low到middle这段是递增的,而从middle+1到high这一段时递减的。于是,在下面的拷贝数据回原数组的过程中,就需要从两端开始,往中间拷贝,从而使回到原数组中的数据再次全部变成递增的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值