算法复习之最优合并问题

    技术2022-07-11  89

    问题

    给定k个排好序的序列s1,s2,…,sk,用2路合并算法将这k个序列合并成一个序列。假设所采用的2路合并算法合并两个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需要的总比较次数最少。

    测试用例:

    4(序列数) 5 12 11 2(序列中的元素数)

    输出:

    78(最差情况) 52(最优情况)

    问题分析

    需要求最优次数和最差次数,采用贪心求解。求最优次数时每次合并最短的两个,求最差时每次合并最长的两个。 仔细想想,这题和霍夫曼编码就是一个事,只不过霍夫曼需要求合并树的路径,这个比他简单点。

    代码

    #include<iostream> using namespace std; int Print(int m[],int n) { for(int i=0;i<n;i++) { cout<<m[i]<<" "; } cout<<endl; } int sort(int num[],int n,int flag) { int t; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { if((num[i]<num[j]&&flag==1)||(num[i]>num[j]&&flag==0)) { t=num[i]; num[i]=num[j]; num[j]=t; } } } } int MinMerge(int num[],int n) { int t=n; sort(num,n,1); n=n-1; int sum=0; while(n>0) { num[n-1]=num[n-1]+num[n]; n--; sum+=num[n]; sort(num,n+1,1); } printf("%d\n",sum); sum-=(t-1); return sum; } int MaxMerge(int num[],int n) { sort(num,n,0); Print(num,n); int t=n; n=n-1; int sum=0; while(n>0) { num[n-1]=num[n-1]+num[n]; n--; sum+=num[n]; sort(num,n+1,0); } printf("%d\n",sum); sum-=(t-1); return sum; } int main() { int n; cin>>n; int num[n]; int num2[n]; for(int i=0;i<n;i++) { cin>>num[i]; num2[i]=num[i]; } int min=MinMerge(num,n); int max=MaxMerge(num2,n); cout<<"最差时间"<<max<<endl; cout<<"最优时间"<<min<<endl; }

    结果:

    Processed: 0.011, SQL: 9