10.求逆序对数

10.给定一个inversion的定义如下:对于一个整型数组A,以及任意的下标i,j,其中i<j,如果A[i]>A[j],我们称它为一个inversion.请设计一种算法用来计算给定数组A中的inversion的个数。

答: 改进归并排序算法。先递归分治,然后合并两段已经由小到大排序的序列为一段降序的序列。排序过程就是消除逆序对的过程。现假设两段有序序列分别是[beg,mid]和[mid+1,end],在归并过程中(i,j分别为两段序列的下标),如果a[i]<a[j],则不会产生逆序对;但当a[i]>a[j]时,就出现逆序对了,出现了多少?既然[beg,mid]是有序的,那么[i-mid]序列就都能与a[j]构成逆序对,故:mid-i+1。逆序对数=两段有序序列排序前的逆序对数+两段有序序列合并过程中发现的逆序对数。一次合并过程需要得到合并中发现的逆序对数,同时在过程结束时得到一个已经排好序的序列,用于下一次合并。

自顶向下实现:

//在原数组上直接升序排序,调用merge时,a[start~mid],a[(mid+1)~end]均已由小到大排好序,调用结束时,a[start~end]也均已降序排好
#define N 10
int merge(int *a, int start, int mid, int end)
{
	int tmp[N];
	int pfisrt = start;
	int psecond = end;
	int ptmp = 0;
        int num_inversion = 0;
	int i;

	while(pfirst <= mid && psecond <= end)
	{
		if(a[pfirst] <= a[psecond])
		{
			tmp[ptmp] = a[pfirst];
			ptmp++;
			pfirst++;
		}else if(a[pfirst] > a[psecond])
		{
			num_inversion += (end - pfirst + 1);
			tmp[ptmp] = a[psecond];
			psecond++;
			ptmp++;
		}		
	}	

	while(pfirst <= mid)
	{
		tmp[ptmp] = a[pfirst];
		ptmp++;
		pfirst++;
	}

	whilt(psecond <= end)
	{
		tmp[ptmp] = a[psecond];
		ptmp++;
		psecond++;			
	}

	for(i = start; i <= end; i++)
	{
		a[i] = tmp[i - start];
	}

	return num_inversion;
}

int count_inversion(int *a, int start, int end)
{
	if(start >= end)
	{
	   return 0;	
	}	

        int mid = start + (end - start)/2;
	
        return count_inversion(a,start,mid)+count_inversion(a,mid+1,end)+merge(a,start,mid,end);	

}



 

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值