分治法的应用-求逆序数

来源:互联网 发布:第九交响曲综合征知乎 编辑:程序博客网 时间:2024/06/06 13:02

最近在MOOC上选了一门课,是Algorithms:Design and Analysis,第一堂课的课后编程作业就是求逆序数,题目是给定10W个无序整数(1-100000),求其逆序数。TXT在这里下载:Download the text file here. (Right click and save link as)。我们知道如何对数列进行归并排序,那么求逆序数时只需加入求逆序数的代码即可。例如 求解两个子序列a[first........mid]与a[mid+1.........last]的过程如下:当我们排列好数组时,子序列本身的逆序数必然为0,逆序数一定出现在子序列之间,对此,若有a[j](mid+1<=j<=last)<a[i](first<=i<=mid),逆序数为mid-i+1。依次的进行递归,即可求得逆序数。

题目的C++代码如下:

#include <iostream>
#include <fstream>
using namespace std;
long long Merge(int a[],int first,int mid,int last,int temp[])
{
    int i=first;
    int j=mid+1;
    int m=mid;
    int n=last;
    int k=0;
    long long count=0;//由于逆序数非常大,所以用long long保存。
    while(i<=m&&j<=n)
    {
        if(a[i]<a[j])
        {
            temp[k++]=a[i++];
        }
        else
        {
            temp[k++]=a[j++];//如果a[i]>a[j],则说明逆序。
            count=count+(m-i+1);
        }
    }
    while(i<=m)
    {
        temp[k++]=a[i++];
    }
    while(j<=n)
    {
        temp[k++]=a[j++];
    }
    for(int i=0;i<k;i++)
    {
        a[i+first]=temp[i];
    }
    return count;
}
long long Mergesort(int a[],int first,int last,int temp[])
{
    long long r1,r2,r;
    if(first<last)
    {
        int mid=(first+last)/2;
        r1=Mergesort(a,first,mid,temp);
        r2=Mergesort(a,mid+1,last,temp);
        r=Merge(a,first,mid,last,temp);
        return (r1+r2+r);
    }
    else
    {
        return 0;
    }
}
int main()
{
    ifstream inFile;
    inFile.open("IntegerArray.txt");
    int a[100000];
    int temp[100000];//辅助数组
    for(int i=0;i<100000;i++)
    {
        inFile>>a[i];
    }
    cout<<Mergesort(a,0,99999,temp)<<endl;
    return 0;
}


0 0