对于归并排序的思想,步骤,这篇博客讲的十分清楚排序算法c语言描述—归并排序,我就依自己对这个排序算法的理解尝试着进行一些补充(针对非递归实现归并排序)。
先上代码:
将SR[i…m]和SR[m+1…n]归并成一个有序的TR[i…n]:
void Merge( int *SR , int *TR , int i , int m , int n )
{
int j , k , l ;
for( k = i , j = m + 1 ; i <= m && j <= n ; k++ )
TR[ k ] = SR[ i ] < SR[ j ] ? SR[ i++ ] : SR[ j++ ] ;
if( i <= m )
for( l = 0 ; l <= m - i ; l++ )
TR[ k+l ] = SR[ i+l ] ; //注意这里不能是TR[k++]=SR[i++],否则TR第n个元素不会被赋值,下面同理
if( j <= n )
for( l = 0 ; l <= n - j ; l++ )
TR[ k+l ] = SR[ j+l ] ;
}
将SR[]中长度为s的子序列两两合并到TR[]中:
void MergePass( int *SR , int *TR , int s , int n )
{
int j , i = 0 ;//如果要从数组下标为1开始排序,令i初值为1即可。
while( i <= n - 2 * s + 1 )
{
Merge( SR , TR , i , i + s - 1 , i + 2 * s - 1 ) ;
i = i + 2 * s ;
}
//是否对i<=n-2*s+1,和i<n-s+1感到迷惑?不要着急,下面会讲解
if( i < n - s + 1 )
Merge( SR , TR , i , i + s - 1 , n ) ;
else
for( j = i ; j <= n ; j++ )
TR[ j ] = SR[ j ] ;
}
归并排序的非递归算法:
void MergeSort1( int *SR )
{
int *TR = ( int * )malloc( sizeof( int ) * 10 ) ;
int k = 1 ;
while( k < 10 )
{
MergePass( SR , TR , k , 10 ) ;
k *= 2 ;
MergePass( TR , SR , k , 10 ) ;
k *= 2 ;
}
}
要彻底弄懂非递归实现归并排序,就要理解MergePass函数。
在刚开始看非递归算法的时候,我对MergePass函数中while,if,else中的i的取值感到迷惑,后来晚上睡觉的时候脑子突然开窍了(你懂的),顿时就豁然开朗了。
下面就通过结合图和代码来帮助理解:
void MergePass( int *SR , int *TR , int s , int n )
{
int j , i = 0 ;
while( i <= n - 2 * s + 1 )
{
Merge( SR , TR , i , i + s - 1 , i + 2 * s - 1 ) ;
i = i + 2 * s ;
}
if( i < n - s + 1 )
Merge( SR , TR , i , i + s - 1 , n ) ;
else
for( j = i ; j <= n ; j++ )
TR[ j ] = SR[ j ] ;
}
对于while循环的i的取值:
while循环里执行的是对两个长度都刚好是s的子序列进行合并。
我们可以想象,当while循环执行完毕,剩下的就是不能两两配对的子序列。
这时候就有两种可能:
- 剩下未配对的子序列的长度 > s,那么可以对一个长度 < s的子序列和一个长度刚好 = s的子序列进行配对,即if中执行的代码
- 剩下未配对的子序列的长度 <= s,这就意味着他不能分出长度为s的子序列来和另一个子序列进行配对,迫于无奈只能把剩下的子序列全部加入到TR[]数组中去了,即执行else的代码。
接下来是if中的判断语句:i < n - s + 1
最后就是else
最后再附上源代码:
#include<stdio.h>
#include<stdlib.h>
void Merge( int *SR , int *TR , int i , int m , int n ) ;
void MergeSort1( int *SR ) ;
void MergePass( int *SR , int *TR , int s , int t ) ;
int main( void )
{
int i ;
int SR1[ 10 ] = { 1 , 5 , 3 , 4 , 6 , 46 , 8 , 41 , -2 , 23 } ;
MergeSort1( SR1 ) ;
for( i = 0 ; i < 10 ; i++ )
printf( "%d " , SR1[ i ] ) ; printf( "\n" ) ;
return 0 ;
}
void Merge( int *SR , int *TR , int i , int m , int n )
{
int j , k , l ;
for( k = i , j = m + 1 ; i <= m && j <= n ; k++ )
TR[ k ] = SR[ i ] < SR[ j ] ? SR[ i++ ] : SR[ j++ ] ;
if( i <= m )
for( l = 0 ; l <= m - i ; l++ )
TR[ k+l ] = SR[ i+l ] ;
if( j <= n )
for( l = 0 ; l <= n - j ; l++ )
TR[ k+l ] = SR[ j+l ] ;
}
void MergePass( int *SR , int *TR , int s , int n )
{
int j , i = 0 ;
while( i <= n - 2 * s + 1 )
{
Merge( SR , TR , i , i + s - 1 , i + 2 * s - 1 ) ;
i = i + 2 * s ;
}
if( i < n - s + 1 )
Merge( SR , TR , i , i + s - 1 , n ) ;
else
for( j = i ; j <= n ; j++ )
TR[ j ] = SR[ j ] ;
}
void MergeSort1( int *SR )
{
int *TR = ( int * )malloc( sizeof( int ) * 10 ) ;
int k = 1 ;
while( k < 10 )
{
MergePass( SR , TR , k , 10 ) ;
k *= 2 ;
MergePass( TR , SR , k , 10 ) ;
k *= 2 ;
}
}