归并排序(递归和非递归)

单趟排序

归并排序单趟的原理是将两个有序的数组归并为一个有序的序列,通过开辟一个新的空间int * p,存储新的数据,再将p中的数据拷贝到原数组中。

void pastsort3(int* a, int begin1,int end1,int begin2 ,int end2,int*p)  //确保m两个的区间[begin1,end1]和[begin2,end2]都是有序的,将两个连续的空间传过来( end1+1 = begin1 )
{
	int left = begin1;
	int right = begin2;
	int Index = begin1;
	while (left <=end1  && right <= end2)
	{
		if (a[left] > a[right])   // 将小的数放入p数组对应的[begin1,end2]区间中
		{
			p[Index++] = a[right++];
		}
		else
		{
			p[Index++] = a[left++];
		}
	}
	while (right <= end2)
	{
		p[Index++] = a[right++];
	}
	while (left <= end1)
	{
		p[Index++] = a[left++];
	}
	//将p中区间[begin1,end2]的数据拷贝到a[begin1,end2]中
	for (int i = begin1; i <= end2; i++)
	{
		a[i] = p[i];
	}
}

这就是单趟排序的过程。

递归函数

void MergeSort(int* a, int left,int right, int* p)
{
	if (right-left <= 0)  // 完成上半部分的分割
	{
		return;
	}
	int mid = (left + right) / 2;
	MergeSort(a, left, mid, p);
	MergeSort(a, mid+1, right, p);                 // 先分成长度全部为1的区间
	pastsort3(a, left, mid, mid + 1, right, p);    //从二叉堆底开始归并,长度为1,必定有序
}
void _MergeSort(int* a, int n)
{
	int* p = new int[n];
	MergeSort(a, 0,n-1, p);
	delete[]p;
}

图示

非递归函数

用迭代方法:如图,直接从递归图的下半部分开始,比递归效率更高,但代码量更多,还要考虑末尾剩下的数。

但不管末尾剩下多少的数,这些数都是有序的,我们只需要在end2大于n-1的时候,将end2改为n-1即可。

令间隔为gap,每一次循环gap要*2(1,2,4,8......),从头开始,每一gap间隔里的数都是有序的,当gap>n的时候结束循环。

void MergeSort2(int* a, int n)
{
	int* p = new int[n];
	int gap = 1;
	while (gap <= n)
	{
		for (int i = 0; i < n; i += gap*2) // 每次归并两个长度为gap的数列(当gap=2时,i==0归并了下标为0 1 2 3的数)
		{
			int begin1 = i;  //  begin1必然有效
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + gap * 2 - 1;    // end2= begin1+gap-1 =i+gap+gap-1=i+gap*2-1 
			if (begin2 >= n)  //  当begin2 >= n时,情况1.(end1==n-1)由于[begin1,end1]已经是有序的,退出循环   情况2. (end1>n-1)[begin1 , n-1]也是有序的	
			{
				break;
			}
			if (end2 >= n)            // 当begin2<n  end2>=n ,改变end2==n-1,将[begin1,end1]与[begin2,n-1]合并
			{
				end2 = n - 1;
			}
			pastsort3(a, begin1, end1, begin2, end2, p);
		}
		gap *= 2;
	}
	delete[]p;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值