分治算法---求解逆序数问题

[实验目的]

基本掌握分治算法的原理.

掌握二路归并排序的算法及递归程序的设计.

【问题描述】 给定一个整数数组A=(a0,a1,,an-1若 i<j 且 ai>aj,则<ai, aj>就是一个逆序对。例如数组(3,1,4,5,2)中,含有4个逆序对。编写一个程序,采用分治法中的二路归并排序算法,递归地求解A中的逆序对的个数,即逆序数。

【提示】采用分治法中的二路归并排序算法,对数组进行排序,在归并各个子序列时,统计逆序对的个数,如下图所示:

参考代码为:

/*****求字符串a的逆序数ans***************/

int ans;   //全局变量,累计逆序数

void Merge(int a[],int low,int mid,int high) //两个相邻有序段归并

{  int i=low;

   int j=mid+1;

   int k=0;

   int *tmp=(char *)malloc((high-low+1)*sizeof(int));

   while(i<=mid && j<=high) //二路归并

   {  if(a[i]>a[j])

      {  tmp[k++]=a[j++];

         ans+=mid-i+1;

      }

      else tmp[k++]=a[i++];

   }

   while(i<=mid) tmp[k++]=a[i++];

   while(j<=high) tmp[k++]=a[j++];

   for(int k1=0;k1<k;k1++) //tmp[0..k-1]=>a[low..high]

       a[low+k1]=tmp[k1];

   free(tmp);

}

【算法时间复杂度分析】

设整个算法的执行时间为T(n),显然Merge(a,0,n/2,n-1)的执行时间为O(n),所以得到以下递推式:

         T(n)=1 n=1

T(n)=2T(n/2)+O(n) n>1

【思考】如果有多组长度相同的整数数列,每一组都求解逆序对数,然后,按“最多逆序数”到“最少逆序数”的顺序输出所有数列。若两个数列的逆序对个数相同,按原始顺序输出它们,该如何修改程序,完成此问题?

符合题意的算法如下:

#include<iostream>
#define MAXN 55
#define MAXM 105
using namespace std;
int ans;
void Merge(char a[],int low,int mid,int high){
    int i=low;
    int j=mid+1;
    int k=0;
    char *tmp=(char *)malloc((high-low+1)*sizeof(int));
    while(i<=mid && j<=high){
        if(a[i]>a[j]){
            tmp[k++]=a[j++];
            ans+=mid-i+1;
        }
        else tmp[k++]=a[i++];
    }
    while(i<=mid) tmp[k++]=a[i++];
    while(j<=high) tmp[k++]=a[j++];
    for(int k1=0;k1<k;k1++)
        a[low+k1]=tmp[k1];
    free(tmp);
}
void Merge_sort(char a[],int low,int high){
    if(low<high){
        int mid=(low+high)/2;
        Merge_sort(a,low,mid);
        Merge_sort(a,mid+1,high);
        Merge(a,low,mid,high);
    }
}
int inversion(char a[],int n){
    ans=0;
    Merge_sort(a,0,n-1);
    return ans;
}
int main(){
    char a[MAXM];
    int n,number;
    cout<<"please input the number of the content:"<<endl;
    cin>>n;
    cout<<"please input the content:"<<endl;
    cin>>a;
    number=inversion(a,n);
    cout<<"逆序数的对数是:"<<number<<endl;
    return 0;
}

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simon_Smith

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值