[算法导论]练习2-4.d求排列中逆序对的数量

转载请注明:http://www.cnblogs.com/StartoverX/p/4283186.html 

题目:给出一个确定在n个不同元素的任何排列中逆序对数量的算法,最坏情况需要Θ(nlgn)时间。(提示:修改归并排序。)

 思路:修改从大到小排序的归并排序。

  归并排序分为三步:分解、解决、合并。

  分解:将排列A分解为A1A2两个子排列。

  解决:递归的从大到小排列A1A2,在此同样递归的求解A1A2的逆序对数量。

  合并:按照递归排序的合并策略从大到小比较A1中的元素[a1,a2,a3…]A2中的元素[b1,b2,b3…]

      1.a1大于b1,则a1大于A2中的所有元素,逆序对的数量加上length(A2),将a1A1中移至输出排列,a2继续与b1比较。

      2.a1小于b1,则b1大于A1中的所有元素,b1不能与A1中的元素构成逆序对,将b1A2中移至输出排列,b2继续与a1比较。

      3.直到A1A2中没有元素,将剩余元素移至输出排列。

    合并后的逆序对的数目为合并前A1A2中逆序对的数目之和加上合并过程中加上的逆序对数。

 

#include<iostream>
using namespace std;

int A[100];
int temp1[100];
int temp2[100];
int merge(int low1,int high1,int low2,int high2){//合并步
    int inver_num=0;//合并中新增的逆序对数目。
    int A_pos=low1;
    int size1=0;//首先将两个待合并数组复制到临时数组中。
    while(low1<=high1){
        temp1[size1++]=A[low1++];
    }
    int size2=0;
    while(low2<=high2){
        temp2[size2++]=A[low2++];
    }
    int i=0,j=0;
    while(size1!=0&&size2!=0){//开始合并
        if(temp1[i]>temp2[j]){
            A[A_pos++]=temp1[i++];
            inver_num+=size2;//逆序对数目增加。
            size1-=1;
        }
        else{//没有相同元素。
            A[A_pos++]=temp2[j++];
            size2-=1;
        }
    }
    
    while(size2!=0){//将剩余的元素复制到输出数组。
        A[A_pos++]=temp2[j++];
        size2-=1;
    }
    while(size1!=0){//和上面的while只会执行一个。
        A[A_pos++]=temp1[i++];
        size1-=1;
    }
    return inver_num;
}
int inversion(int low,int high){
    if(low>=high)
        return 0;
    int mid=(low+high)/2;
    int left_num=inversion(low,mid);
    int right_num=inversion(mid+1,high);
    int merge_num=merge(low,mid,mid+1,high);
    return left_num+right_num+merge_num;
}

int main(){
    int size;
    cin>>size;//输入数组大小。
    for(int i=0;i<size;i++){//输入数组。
        cin>>A[i];
    }
    cout<<inversion(0,size-1)<<endl;
}

 

posted @ 2015-02-10 10:27  TimCheng  阅读(1315)  评论(0编辑  收藏  举报