转自:http://blog.csdn.net/forget_me_not1991/article/details/40394225
网上有很多关于逆序对的计算方法及源代码,我仅仅在这里记录下自己的理解
逆序对:设a[0…n]为包含n个不数的一个序列,如果n<m,且a[n]>a[m],则称(n,m)构成a中的一个逆序对;
问题:给出一个数字序列,找出其逆序对的个数;
解答:
本文主要介绍采用归并排序算法计算逆序对;
主要思想为将数组分成两份,这样所有的逆序对由三部分组成:1.前半部分的逆序对;2.后半部分的逆序对;3.前后两部分之间的逆序对;
然后1,2中的逆序对可以分解为本问题的一个子问题,适合采用递归求解; 源代码如下:
#include <iostream>
#include <vector>
using namespace std;
int countReversed(vector<int> &a, int begin,int end);
int merge(vector<int> &a, int begin, int mid, int end);
int main()
{
vector<int> arr;
int num = 0;
int count;
cout << "input the number of data " << endl;
cin >> count;
cout << "input data :" << endl;
for (int i = 0; i < count; ++i)
{
cin >> num;
arr.push_back(num);
}
cout << "result is : " << countReversed(arr, 0, arr.size() - 1) << endl;
getchar();
return 0;
}
int countReversed(vector<int> &a, int begin,int end)
{
if (begin < end)
{
int mid = (begin + end) / 2;
return (countReversed(a, begin, mid) +
countReversed(a, mid + 1, end) + merge(a, begin, mid, end));
}
else
{
return 0;
}
}
//计算前后之间逆序对的个数,因为这部分在计算完数组前半部分逆序数和后
//半部分逆序数之后计算,所以在计算两部分之间的逆序对的同时,对数组进行
//归并排序
int merge(vector<int> &a, int begin, int mid, int end)
{
int nCount = 0; //前后两段之间逆序的个数
vector<int >b;
int j = begin, k = mid + 1;
int n = end - begin + 1;
int i = 0;
for (i = 0; i < n ; ++i)
{
if (j > mid || k > end)
{
break;
}
if (a.at(j) <= a.at(k))
{
b.push_back(a.at(j));
++j;
}
else
{
b.push_back(a.at(k));
nCount += mid - j + 1;
++k;
}
}
while (j <= mid)
{
b.push_back(a.at(j));
++j;
}
while (k <= end)
{
b.push_back(a.at(k));
++k;
}
for (i = 0; i < n; ++i)
{
a[begin + i] = b[i];
}
return nCount;
}