合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个 N/2 个长度为2或1的有序子序列,再两两合并,如此重复,值得得到一个长度为N的有序数据序列为止,这种排序方法称为2路合并排序。
例如数组A有7个数据,分别是: 49 38 65 97 76 13 27,那么采用归并排序算法的操作过程如图所示:
初始值 [49] [38] [65] [97] [76] [13] [27]
看成由长度为1的7个子序列组成
第一次合并之后 [38 49] [65 97] [13 76] [27]
看成由长度为1或2的4个子序列组成
第二次合并之后 [38 49 65 97] [13 27 76]
看成由长度为4或3的2个子序列组成
第三次合并之后 [13 27 38 49 65 76 97]
归并排序算法过程图
合并算法的核心操作就是将一维数组中前后相邻的两个两个有序序列合并成一个有序序列。合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。
而逆序数就是左边序列比右边序列大的数对。设i和j两个指针指向left和right序列,起始为1,n1n2是序列的长度。当a数列插入k为right数列中j时,逆序数增加为n1 - i + 1。如第三次合并中13插入k=1时,ans+=4 - 1 + 1
...{
if(p<r)
...{
int q=(p+r)/2;
mergesort(a,p,q);
mergesort(a,q+1,r);
merge(a,p,q,r); //合并步骤 p<=left<=q q<right<=r;
}
}
void merge(long a[],int p,int q,int r)
...{
int n1=q-p+1;
int n2=r-q;
int i,j,k;
long left[n1+1];
long right[n2+1];
for(i=1;i<=n1;i++)
left[i]=a[p+i-1];
for(j=1;j<=n2;j++)
right[j]=a[q+j];
left[n1+1]=1e9; //设置一个哨兵
right[n2+1]=1e9; //同上
i=1;
j=1;
for(k=p;k<=r;k++)
if(left[i]<right[j])
a[k]=left[i++];
else
...{
a[k]=right[j++];
ans+=n1-i+1; //计数;
}