根据归并排序的思想,在每次归并的时候,需要对划分的两个区域,如下图中的蓝色和黄色区域,然后将temp[i]和temp[j]进行比较,将较小的值(此处对数组进行从小到大排序)存放到原数组arr中
在这个归并的过程中,就可以进行逆序对的统计,由于归并时的数组划分的两个区域已经排序完毕,所以数组是有序的,这时,假如temp[i]>temp[j],那么temp[i,mid]这个区间的所有数都大于temp[j],逆序对的个数就是mid-i+1。根据这个原理对逆序对个数进行统计。
下面的代码以5 7 3 1 8 6 4 为例,统计逆序对个数,先自己统计一下,发现这里面有11组逆序对。
// 归并排序求逆序对的个数.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "E:/学习/C++/数据结构和算法/code/算法/排序算法/common/sortTestHelper.h"
using namespace std;
template <typename T>
long long calculate(T *arr,int l,int mid,int r)
{
long long count = 0;
T *temp = new T[r - l + 1];
for (size_t p = 0; p < r-l+1; p++)
{
temp[p] = arr[p + l];
}
int i = 0, j = mid+1-l;
for (size_t k = l; k <= r; k++)
{
if (i>mid-l)
{
arr[k] = temp[j];
j++;
}
else if (j > r - l)
{
arr[k] = temp[i];
i++;
}
else
{
if (temp[i]<temp[j])
{
arr[k] = temp[i];
i++;
}
else
{
arr[k] = temp[j];
j++;
count += (long long)(mid - l - i + 1);
}
}
}
delete[] temp;
return count;
}
template <typename T>
long long InversionPair(T *arr,int l,int r)
{
if (l>=r)
{
return 0;
}
int mid = (l + r) / 2;
long long count1=InversionPair(arr, l, mid);
long long count2 = InversionPair(arr, mid + 1, r);
long long count3=calculate(arr, l, mid, r);
return count1 + count2+count3;
}
int main()
{
int n = 7;
int arr[7] = {5,7,3,1,8,6,4};
long long count=InversionPair(arr, 0, n - 1);
SortTestHelper::printArr(arr, n);
printf("逆序对的个数=%d\n", count);
return 0;
}
最终结果显示正确