自然合并排序(详细代码注释)

 由于解释都在代码里,我就直接放代码了。

#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") ;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值