归并排序
1.简单介绍:
采用的叫分治的思想,将数组划分为两个子数组,然后递归将每个子数组再进行划分,直到数组中只剩一下一个元素,然后开始排序合并,直到将所有的子数组合并完成,整个数据就是有序的啦。时间复杂度:NlogN。
2.原理
图解
思路:先将无序序列利用二分法划分为两个子序列,直至每个子序列只有一个元素,一个元素序列必然有序,然后再对有序子序列两两进行合并排序。合并方法是循环的将两个有序子序列当前的首元素进行比较,较小的元素取出,放入合并序列的左边空置位,直至其中一个子序列的最后一个元素放入合并序列中。最后将另一个子序列的剩余元素按顺序逐个放入合并序列尾部。
3.代码:
排序过程:
int c[1000],a[1000];
void paixu(int a[1000],int l,int mid,int r)
{
long long int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])
c[k++]=a[i++];
else
{
m+=mid-i+1;
c[k++]=a[j++];
}
}
while(i<=mid)
c[k++]=a[i++];
while(j<=r)
c[k++]=a[j++];
for(i=l;i<=r;i++)
{
a[i]=c[i-l];
}
}
归并过程
void merge(int a[1000],int l,int r)
{
int mid;
if(l==r)
return;
mid=(l+r)/2;
merge(a,l,mid);
merge(a,mid+1,r);
paixu(a,l,mid,r);
}
4.例题:
求逆序数。
样例
样例输入 Copy
2
2
1 1
3
1 3 2
样例输出 Copy
0
1
在归并的基础上加上sum即可
代码:
#include<stdio.h>
long long int sum=0;
long long int c[10000],a[10000];
void paixu(long long int a[],long long int l,long long int mid,long long int r)
{
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])
c[k++]=a[i++];
else
{
c[k++]=a[j++];
sum+=mid-i+1;
}
}
while(i<=mid)
c[k++]=a[i++];
while(j<=r)
c[k++]=a[j++];
for(i=l;i<=r;i++)
{
a[i]=c[i];
}
}
void merge(long long int a[],long long int l,long long int r)
{
long long int mid;
if(l<r)
{
mid=(l+r)/2;
merge(a,l,mid);
merge(a,mid+1,r);
paixu(a,l,mid,r);
}
}
int main()
{
long long int n,i,t;
scanf("%lld",&t);
while(t--)
{
sum=0;
scanf("%lld",&n);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
merge(a,0,n-1);
printf("%lld\n",sum);
}
return 0;
}
5.心得:又了解到一个新的排序方法,与之前学到的相比时间复杂度要小,解题时可根据时间限制,和题目所需巧用各种排序方法。
来源:CSDN
作者:huyidai
链接:https://blog.csdn.net/huyidai/article/details/104044646