现在的位置: 首页 > 综合 > 正文

并归排序法求逆序数

2013年10月22日 ⁄ 综合 ⁄ 共 2286字 ⁄ 字号 评论关闭

逆序对(inversion pair)是指在序列{a0,a1,a2...an}中,若ai<aj(i>j),则(ai,aj)上一对逆序对。而逆序数 (inversion number)顾名思义就是序列中逆序对的个数。例如: 1 2 3是顺序,则逆序数是0;1 3 2中(2,3)满足逆序对的条件,所以逆序数只有1; 3 2 1中(1,2)(1,3)(2,3)满足逆序对,所以逆序是3。由定义不难想象,序列n的逆序数范围在[0,n*(n-1)/2],其中顺序时逆序数为 0,完全逆序时逆序数是n*(n-1)/2。
就我所知,目前求这种逆序对最快的算法是利用归并排序,其时间复杂度为O(nlgn), 空间复杂度为O(n)。

代码如下:view plaincopy to clipboardprint?
#include <iostream>  
#include <cstring>  
using namespace std;  
long c[500005];  
long a[500005];  
long b[500005];  
long long num=0;  
const long MAX=1000000000;  
void merge(int s,int p,int e)  
{  
    memcpy(a,c+s,sizeof(long)*(p-s+1));  
    memcpy(b,c+p+1,sizeof(long)*(e-p));  
      
    int l1 = p-s+1;  
    int l2 = e-p;  
    a[l1] = b[l2] = MAX;//在比较过程中设置尾部哨兵  
    int i =0;  
    int j = 0;  
    int k =0;  
    /* 
    while(i<l1 && j<l2) 
    { 
        if(a[i]<b[j]) 
        { 
                c[k++] = a[i]; 
                i++; 
        } 
        else if(a[i]>b[j]) 
        { 
                c[k++]=b[j]; 
                j++; 
        } 
        else 
        { 
                c[k++]=a[i]; 
                i++; 
                j++; 
        } 
    } 
    */ 
    //a[i]表示前半部分  
    //b[i]表示后半部分  
    //逆序数的表现位:  
    //i<j && v[i]>v[j]  
    for(k=s;k<=e;k++)  
    {  
            if(a[i]<=b[j])  
            {  
                    c[k]=a[i];  
                    i++;  
            }  
            else 
            {  
                    c[k]=b[j];  
                    j++;  
                    num+=l1-i;  
            /* 
            此时就表现出了逆序数的特征,因为a[i]>b[j],并且a和b中数据都有序,所以a[i+1,...,l1]>b[j],故num增加l1-i。 
            比如a={4,7,9,MAX} 
               b={5,6,8,MAX} 
                           当i=1时,a[i]=7,此时a[i]>b[j]=5,并且a[i+1]=9>b[j],此时num增加l1-i=2; 
            */ 
            }  
    }  
}  
void merge_sort(int s,int e)  
{  
        if(s<e)  
        {  
                int p = (e+s)/2;  
                merge_sort(s,p);  
                merge_sort(p+1,e);  
                merge(s,p,e);  
        }  
}  
int main()  
{  
        int n ;  
        int i = 0;  
        cin>>n;  
        while(n!=0)  
        {  
            i = 0;  
            memset(a,0,sizeof(0));  
            memset(b,0,sizeof(0));  
            memset(c,0,sizeof(0));  
            num=0;  
            for(i=0;i<n;i++)           
                    cin>>c[i];  
            merge_sort(0,n-1);  
            cout<<num<<endl;  
            cin>>n;  
        }  

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/05/10/4165642.aspx

抱歉!评论已关闭.