又是好长时间没有写博客了,刚参加完成都赛区的亚洲赛,尽管和两位学长一起努力得了一个铜奖,但是感觉自己和那里其他大牛的差距太大!
所以,我决定要利用接下来一年的时间学好算法,好好努力,目标是明年亚洲赛 拿一块金奖!
下面介绍一下用归并排序求逆序数!感觉有一点和线段树很相似,就是从中间分开!
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
归并操作的工作原理如下:
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;
}
浙公网安备 33010602011771号