算法导论2-4习题解答(合并排序算法)

CLRS 2-4 :要求用O(nlgn)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目。(提示:修改合并排序)

算法思想:
逆序对,即i < j时,有a[i] > a[j],那么我们可以修改合并排序,每次合并时,都把这样的对数记下来即可,因为合并排序是从最底部开始的(书上给出了一个树形图)。

代码如下:

#include <iostream>
using namespace std;

//寻找一个数组中的逆序对
//逆序对:
//i < j时,有a[i] > a[j]

//算法思想:修改合并排序
#define LEN 5

void merge(int* a, int p, int q, int r, int&count)
{
    int* left =new int[q-p+1];
    int* right =new int[r-q];
    for(int i =0; i < q-p+1; i++)
        left[i] = a[p+i];
    for(int i =0; i < r-q; i++)
        right[i] = a[q+i+1];

    int m =0;
    int n =0;
    for(int i = p; i <= r; i++)
    {
        if(left[m] > right[n])
        {
            count += r - q - n;
            a[i] = left[m];
            if(m++== q-p)
            {
                for(int j = i +1; j <= r; j++)
                    a[j] = right[n++];
                break;
            }
        }
        else
        {
            a[i] = right[n];
            
            if(n++== r-q-1)
            {
                for(int j = i+1; j <= r; j++)
                    a[j] = left[m++];
                break;
            }
        }
    }
    delete[] left;
    delete[] right;
}
void sort(int* a, int m, int n, int&count)
{
    if(m < n)
    {
        int middle = (m + n)/2;
        sort(a, m, middle, count);
        sort(a, middle+1, n, count);
        merge(a, m, middle, n, count);
    }
}

int main()
{
    int* a =new int[LEN];
    //for(int i = 0; i < LEN; i++)
    //    a[i] = 10 - i;
    a[0] =2;
    a[1] =3;
    a[2] =8;
    a[3] =6;
    a[4] =1;
    int count =0;

    sort(a, 0, LEN -1, count);
    cout<<count<<endl;
    for(int i =0; i < LEN; i++)
        cout<<a[i]<<endl;
    delete[] a;
    return 0;
}

 

posted on 2011-03-20 19:39  NULL00  阅读(1807)  评论(0编辑  收藏  举报

导航