您的位置:首页 > 其它

nyoj 322 117 求逆序数 归并排序

2016-05-17 17:51 190 查看
此题相当于问冒泡从小大大排序中交换了多少次,但是冒泡的时间复杂度的n^2,所以不可取,可以换用归并排序,归并排序时间复杂度为nlogn,还行,之前只听过归并排序的概念(毕竟有sort),没有敲过代码,这次参考别人的博客水一发,

比如现在有两组已经从小到大排好的数据 5 10 15 17和3 9 11 12 30

要将这两组数据整合到一起,同时按从小到大排序

那么可以先比较两组数据的第一个数字 5 和3,3小,取3,同时去掉3,再比较5 和9,取5同时去掉5,再比较10和9,9小取9同时去掉,以此类推,得到3 5 9 10 11 12 15 17 30 如果现在有一组数据要排大小的话,我们就可以将这一组数据分成两组,同时这两组的每一组再分成两组,直到每组数据为两个数(也可能为1个数),然后比较排序,这样就得到了已经排好序的数据,再两两比较类似于上面的例子,重新整合到一块。

概念容易理解,但是代码不是很好理解:

#include<stdio.h>
int a[1000010],b[1000010];
long long s=0;
void sort(int first,int mid,int last)
{
int i=first,k=first,j=mid+1;
while(i<=mid&&j<=last)  //先将左一半或右一半的数据取完,
{
if(a[i]<=a[j])
b[k++]=a[i++];
else
s+=j-k,b[k++]=a[j++];    //s+=j-k是关键,想想为什么,^_^
}
while(i<=mid)  //剩下的数据均是大的,所以取完 因为不知道到底是左一半先取完还是右一半先取完,所以两者都尝试
b[k++]=a[i++];
while(j<=last)//剩下的数据均是大的,所以取完
b[k++]=a[j++];
for(i=first; i<=last; i++)  //再重新将b[]赋值给a[]
a[i]=b[i];
}
void msort(int first,int last)
{
int mid=(first+last)/2;
if(first<last)  //一直递归直到first==last
msort(first,mid),msort(mid+1,last),sort(first,mid,last);  //先把左一半和右一半排序,然后再整合
}
int main()
{
int nn;
scanf("%d",&nn);
while(nn--)
{
int n,i;
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%d",&a[i]);
s=0;
msort(1,n);
printf("%lld\n",s);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: