递归之合并排序

合并排序算法是用分治的策略实现对n个元素进行排序的算法。其基本思想是:将待排序的元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。合并排序算法可以递归地描述如下:
template <class T>
void MergeSort( T a[], int left, int right ){
	
	if( left < right ){ //至少要有2个元素
		int i = ( left + right ) / 2; // 取中点
		MergeSort( a, left, i );	//对左边进行排序
		MergeSort( a, i + 1, right );//对右边进行排序
		Merge( a, b, left, i, right );//合并到数组b,真正进行排序就是在这里进行的
		Copy( a, b, left, right );	//复制回数组a
	}
	
}

这个递归方程T( n ) = O( nlongn )。由于排序问题的计算下界为Ω(nlongn),所以啊合并算法是一个渐进最优的算法。下面举个例子。

对于算法MergeSort,还可以进行改进,例如我们可以消除递归。事实上,算法MergeSort的递归过程只是将待排序集合一分为二,直至只剩下一个元素为止,然后不断的合并两个排序号的数组段。按此机制,可以首先将数组a中相邻元素两两配对。用合并排序将他们排序,构成n / 2组长度为2的排好序的子数组段,然后将他们排序成长度为4的排好序的子数组段,如此继续下去,直至整个数组排好序。

按此思想,相除递归的合并排序算法可以描述如下:

template <class T>
void MergeSort( T a[], int n ){
	//消除递归的做法
	T* b = new T[n];
	int s = 1;
	while( s < n ){
		MergePass( a, b, s, n );//合并到b数组
		s += s;
		MergePass( b, a, s, n );//合并到a数组
		s += s;
	}
}
其中,需要重载T类型元素的“<=”符号。

下面给出其他出现函数的代码

template <class T>
void Merge( T a[], T b[], int l, int m, int r ){
	int i = l;
	int j = m+1;
	int k = l;
	while( i <= m && j <= r )
		if( a[ i ] <= a[ j ] ) b[k++] = a[i++]; //较小的放在前面
		else b[k++] = a[ j++ ];
	if( i > m )for( int q = j; q <= r; ++q ) b[ k++ ] = a[ q ];//左边还有元素没有放进b时,
	else for( int q = i; q <= m; ++q ) b[ k++ ] = a[ q ];//右边还有元素没有放进b时,
}


 

template <class T>
void MergePass( T x[], T y[], int s, int n ){
	int i = 0;
	while( i <= n - 2 * s ){//预留出2 * s个位置,
		Merge( x, y, i, i + s - 1, i + 2 * s - 1 );
		i += 2 * s;
	}
	if( i + s < n )Merge( x, y, i, i + s - 1, n - 1 ); //要合并的左右子集中,左子集够s个,但是右子集不够
	else for( int j = i; j <= n - 1; ++j ) y[j] = x[j]; //要合并的左右子集中,连左子集都不够s个了
}
template <class T>
void Copy( T a[], T b[], int l, int r ){
	int i;
	for( i = l; i <= r; ++i ){
		a[ i ] = b[ i ];
	}
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值