又是好长时间没有写博客了,刚参加完成都赛区的亚洲赛,尽管和两位学长一起努力得了一个铜奖,但是感觉自己和那里其他大牛的差距太大!

所以,我决定要利用接下来一年的时间学好算法,好好努力,目标是明年亚洲赛 拿一块金奖!

下面介绍一下用归并排序求逆序数!感觉有一点和线段树很相似,就是从中间分开!

归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并操作的工作原理如下:   

1、 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列   

2、 设定两个指针,最初位置分别为两个已经排序序列的起始位置   

3、 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置   

4、 重复步骤3直到某一指针达到序列尾   将另一序列剩下的所有元素直接复制到合并序列尾

重要用途 : 可以用来求逆序对数!

代码如下(既排序带求逆序数):

# include<stdio.h>
int count;
void merge(int array[],int p,int q,int r) /////  p < = q < r
{
	int begin1,end1,begin2,end2,k,temp[1000];
	begin1=p;
	end1=q;
	begin2=q+1;
	end2=r;
	k=0;
	while(begin1<=end1 && begin2<=end2)
	{
		if(array[begin1] < array[begin2])
		{
			temp[k++]=array[begin1];
			begin1++;
			count+=begin2-(q+1);
		}
		else 
		{
			temp[k++]=array[begin2];
			begin2++;
		}
	}
	while(begin1<=end1)
	{
		temp[k++]=array[begin1];
		begin1++;
		count+=end2-q;
	}
	while(begin2<=end2)
	{
		temp[k++]=array[begin2];
		begin2++;
	}
	for(int i=p;i<=r;i++)
		array[i]=temp[i-p];
}
void mergesort(int array[],int first,int last)
{
	int mid=(first+last)/2;
	if(first<last)
	{
		mergesort(array,first,mid);
		mergesort(array,mid+1,last);
		merge(array,first,mid,last);
	}
}
int main()
{
	int i,n,array[1000];
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
			scanf("%d",&array[i]);
		count=0;
		mergesort(array,1,n);
		for(i=1;i<=n;i++)
			printf("%d ",array[i]);
		printf("\n");
		printf("%d\n",count);
	}
	return 0;
}
posted on 2010-11-12 20:47  奋斗青春  阅读(3534)  评论(4编辑  收藏  举报