排序专题之归并排序

归并排序:

基本思想是将两个或两个以上有序表合并成一个新的有序表。
假设初始序列含有n个记录,首先将这n个记录看成n个有序的子序列,
每个子序列的长度为1,然后两两归并,得到?n/2?个长度为2(n为奇数时,
最后一个序列的长度为1)的有序子序列;在此基础上,再进行两两归并,
如此重复,直至得到一个长度为n的有序序列为止。这种方法被称作2-路归并排序。 


下面请看代码实现:

代码一:


void Mergesort(Record s[],Record a[],int left,int right)
{
	int middle;
	if(left<right)
	{
		middle=(left+right)/2;
		Mergesort(s,a,left,middle);
		Mergesort(s,a,middle+1,right);
		guibing(s,a,left,right,middle);
	}
} 

void guibing(Record s[],Record a[],int left,int right,int middle)
{
	int t1,t2,i,j;
	for(i=left;i<right;i++)
	{
		a[i]=s[i];
	}
	t1=left,t2=middle+1;
	i=left;
	while(t1<=middle&&t2<=right)
	{
		if(a[t1]<=a[t2])
			s[i++]=a[t1++];
		else s[i++]=a[t2++];
	}
	while(t1<=middle)
	{
		s[i++]=a[t1++];
	}
	while(t2<=right)
	{
		s[i++]=a[t2++];
	}
}




优化避免后面的t1 t2 要查看其长度,把后面的子数组的
顺序在转移的时候替换顺序;


void Mergesort(Record s[],Record a[],int left,int right)
{
	int middle;
	if(right-left+1>28)
	{
		middle=(left+right)/2;
		Mergesort(s,a,left,middle); //左一半进行递归 
		Mergesort(s,a,middle+1,right); //右一半进行递归 
		guobing(s,a,left,right,middle);
	}
	else charu(&a[left],right-left+1);//若序列短的  直接用插入排序 
} 

void guibing(Record s[],Record a[],int left,int right,int middle)
{
	int t1,t2,i,j,k;
	for(i=left;i<=middle;i++)
	{
		a[i]=s[i];
	}
	for(j=1;j<=right-middle;j++)
	{
		a[right-j+1]=s[j+middle];
	}
	for(t1=left,t2=right,k=left;k<=right;k++)
	{
		if(a[t1]<=a[t2])
		{
			s[k]=a[t1++];
		}
		else s[k]=a[t2--];
	}
	
}

归并排序中一趟归并中要多次用到2-路归并算法,
一趟归并排序的操作是调用n/2h次算法merge 将r1[1…n]中前后
相邻且长度为h的有序段进行两两归并,得到前后相邻、长度为2h的有序段,并存放在r[1…n]中,
其 时间复杂度为O(n)。整个归并排序需进行m(m=log2n)趟2-路归并,
所以归并排序总的时间复杂度为O(nlog2n)。
在实现归并排序时,需要和待排记录等数量的辅助空间,空间复杂度为O(n)。 
归并排序的最大特点是,它是一种稳定的排序方法



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值