排序 - 归并排序

将两个有序表合并成一个有序表的过程称为2路归并;

区别于前几种排序方法,这个排序方法是用递归实现,其中体现了分治的思想。

归并排序思想:假设初始序列含有n个记录(元素),则可以看作是n个有序的子序列,其中每个序列的长度为1,然后两两归并。得到n/2个长度为2的有序子序列;然后再两两归并,形成n/4个子序列……重复执行(递归,终止条件为形成1个子序列),直到得到一个长度为n的有序序列。即排序完成。

将两个有序序列合成一个有序序列的过程:

假设有两个有序X,Y序列,放在同一个顺序表a[low,high]当中,其中一个在a[low,mid]中,另一个在[mid+1,high]中,每次从两个表中取出一个元素进行比较,将较小的一个存入一个顺序表B[low,high]中,重复这个过程,直到两个有序表中其中一个为空,然后将不为空的那一个按顺序复制到B中。

C代码实现:

void Merge (int a[],int low,int mid,int high){
	int i,p,l,h;//定义下表p,用于B[]      下标l,h分别指向剩余部分的头,和尾 
	int *B=(int*)malloc((high-low+1)*sizeof(int));//动态申请一个临时数组B[] 
	int k1_low=low,k1_high=mid;
	int k2_low=mid+1,k2_high=high;
	for(p=0;k1_low<=k1_high&&k2_low<=k2_high;p++){//每次从K1,K2中取出一个元素进行比较,将较小的存入B[] 
		if(a[k1_low]<=a[k2_low])
			B[p]=a[k1_low++];
		else
			B[p]=a[k2_low++];
	}

	if(k1_low>k1_high){//当k1_low>k1_high时,证明k1先结束 
		l=k2_low;
		h=k2_high;
	} 
	else if(k2_low>k2_high){//相反则证明k2先结束 
		l=k1_low;
		h=k1_high;
	}
	while(l<=h){//将剩余的部分复制到B[]中 
		B[p++]=a[l++];
	} 
	for(i=0;i<high-low+1;i++){//将重新组合的部分重新拷入原数组的同一个地方 
		a[low+i]=B[i];
	} 
	for(i=0;i<N;i++){
		printf("%d\t",a[i]);
	}
	printf("\n");
	free(B);//释放动态申请的空间 
	return;
}

归并排序算法描述:将一个无序表a[low,high]进行归并排序,并存入B[low,high]。

1>将当前序列一分为2,并求出分裂点mid=(low+high)/2,并向下取整。       2>对于a[low,mid]递归,进行归并排序,并存入中间顺序表K1      3>对于a[low,high]进行递归,进行归并排序,并存入中间顺序表K2      4>对于生成的K1,K2这两个有序表进行合并。将新生成的有序表返回。

整体C语言描述:

#include <stdio.h>   //需要使用基本输入输出函数 
#include <stdlib.h>  //需要使用malloc(),free() 函数 
//归并排序

#define N 10 

void Merge (int a[],int low,int mid,int high){
	int i,p,l,h;//定义下表p,用于B[]      下标l,h分别指向剩余部分的头,和尾 
	int *B=(int*)malloc((high-low+1)*sizeof(int));//动态申请一个临时数组B[] 
	int k1_low=low,k1_high=mid;
	int k2_low=mid+1,k2_high=high;
	for(p=0;k1_low<=k1_high&&k2_low<=k2_high;p++){//每次从K1,K2中取出一个元素进行比较,将较小的存入B[] 
		if(a[k1_low]<=a[k2_low])
			B[p]=a[k1_low++];
		else
			B[p]=a[k2_low++];
	}

	if(k1_low>k1_high){//当k1_low>k1_high时,证明k1先结束 
		l=k2_low;
		h=k2_high;
	} 
	else if(k2_low>k2_high){//相反则证明k2先结束 
		l=k1_low;
		h=k1_high;
	}
	while(l<=h){//将剩余的部分复制到B[]中 
		B[p++]=a[l++];
	} 
	for(i=0;i<high-low+1;i++){//将重新组合的部分重新拷入原数组的同一个地方 
		a[low+i]=B[i];
	} 
	printf("\n");
	free(B);//释放动态申请的空间 
	return;
}

void MSort(int a[],int low,int high){
	int mid=0;
	if(low<high){
		mid=(low+high)/2;
		MSort(a,low,mid);
		MSort(a,mid+1,high);
		Merge(a,low,mid,high);
	}
	return;
}

int main (void){
	int i;
	int a[N]={9,2,6,3,5,1,7,8,4,0};
	for(i=0;i<N;i++){
		printf("%d\t",a[i]);
	}
	printf("\n");
	MSort(a,0,9);
	for(i=0;i<N;i++){
		printf("%d\t",a[i]);
	}
}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值