递归之合并排序

来源:互联网 发布:倩女手游 mac 编辑:程序博客网 时间:2024/05/02 01:42
合并排序算法是用分治的策略实现对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 ];}}





0 0
原创粉丝点击