由于解释都在代码里,我就直接放代码了。
#include <stdio.h>
int t[100] ;
int a_index[100] ; //存储有序的数组段的下标
int a_lenth ; //a_index[]的长度
void Merge(int c[], int d[], int l, int m, int r){ /*合并两个连续的子数组段,以后会发一个合并排序的递归算法详细说
这个函数*/
int i = l, j = m+1, k = l ;
while ( ((i<=m) && (j<=r)) ){
if( c[i]<c[j] )
d[k++] = c[i++] ;
else
d[k++] = c[j++] ;
}
while(i<=m)
d[k++] = c[i++];
while(j<=r)
d[k++] = c[j++];
}
void GetBPoint(int a[],int n) /*得到各个有序数组段的下标,例如:1 2 5 4 6 a_index[]存储的是{0, 3}*/
{
int j=0;
a_index[j++]=0;
for(int i=0;i<n-1;i++){
if(a[i+1]<a[i])
a_index[j++]=i+1;
}
a_lenth = j;
}
void MergePass(int x[],int y[],int roundNum,int n) /*MergePass表示合并一趟有序数组;roundNum表示合并的子数组段
个数(开始是1,表示合并两个长度为1的子数组)*/
{
int i=0;
while(i <= a_lenth-2*roundNum){ /*剩下的下标还能合并两个数组(循环合并,直到剩下的下标不能合并两个下标为止)*/
int r=((i+2*roundNum) < a_lenth) ? a_index[i+2*roundNum] : n ; /*r表示合并的第二个子数组
a_index[...:r]的后面的下标*/
Merge(x,y,a_index[i],a_index[i+roundNum]-1,r-1); //合并两个子数组
i=i+2*roundNum; //更新i
}
if(i+roundNum < a_lenth) //表示剩下的下标不够合并两个数组段(只够一个数组段)
Merge(x,y,a_index[i],a_index[i+roundNum]-1,n-1); /*直接将多出来的这个数组段与后面不够合并的半个或
一个数组段合并*/
else
if(i<a_lenth){ /*表示剩下的下标只支撑半个数组段的合并,所以直接将这半个已经有序的数组段加在数组的最后*/
for(int j=a_index[i]; j<=n-1; j++)
y[j]=x[j];
}
}
void mergeSort(int a[], int n){
int s = 1 ;
while ( s < n ){ //s表示合并的子数组段个数,与上面的RoundNum同义
MergePass(a, t, s, n) ; /*MergePass()需要执行两次的原因是需要循环的更新a数组的值的话,一个数组是
不够的,需要通过t和a交换更新值*/
s = s + s ;
MergePass(t, a, s, n) ;
s = s + s ;
}
}
int main()
{
int n, i ;
int a[100] ;
printf("请输入待排序数组个数:") ;
scanf("%d", &n) ;
printf("请输入待排序数组:") ;
for( i=0; i<n; i++){
scanf("%d", &a[i]) ;
}
GetBPoint(a,n);
mergeSort(a,n);
printf("排序后数组:") ;
for( i=0; i<n; i++){
printf("%d ", a[i]) ;
}
printf("\n") ;
}