C++计算逆序对

转自: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;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值