第四章上机实践报告 第四章实践报告

第四章实践报告

1.实践题目

4-3 最优合并问题 (100 分)

题目来源:王晓东《算法设计与分析》

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

输入样例:

4

5 12 11 2

输出样例:

78 52

 

2.问题描述

将几个序列合并成一个序列,序列的比较次数的计算方式是序列长度分别为m和n的序列为m+n-1 次。序列的最差合并顺序就是先合并长的再合并短的,序列的最优合并顺序应优先合并最短的。

3.算法描述

Min_sum=(2+5-1)+(2+5+11-1)+(2+5+11+12-1)=52

Max_sum=(12+11-1)+(12+11+5-1)+(12+11+5+2-1)=78

计算最优合并顺序,先将序列长度进行升序排序,合并最短的两个序列,用min_sum记录比较次数,min_sum=a[min_index]+a[min_index+1]-1,用a[min_index]存放合并之后的那个序列,同时将a[min_index+1]置为0,min_index++;再重新排序得到新的列表。(重新排序的原因是因为合并之后的序列有可能比原先的序列都大,这个有点类似哈夫曼树)。以上重复n-1次。

计算最差合并顺序则与上类同。(另附:最差有只排序一次的算法)

复制代码
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;

int main()
{
    int n;
    cin >> n;
    int a[n], b[n], i = 0;
    while(i < n)
    {
        cin >> a[i];
        b[i] = a[i];
        i++;
    }

    //最小
    sort(a, a + n, less<int>());
    int min_index = 0, min_sum = 0;
    while(min_index < n-1)
    {
        min_sum = min_sum + a[min_index] + a[min_index + 1] - 1;
        a[min_index] = a[min_index] + a[min_index + 1];
        a[min_index + 1] = 0;
        min_index++;
        sort(a, a + n, less<int>());
    }

    //最大
    sort(b, b + n, greater<int>());
    //for(int i = 0; i < n; i ++) cout << b[i] << " "; cout << endl;
    int max_index = 0, max_sum = 0;
    while(max_index < n - 1)
    {
        max_sum = max_sum + b[max_index] + b[max_index + 1] - 1;
        b[max_index] = b[max_index] + b[max_index + 1];
        b[max_index + 1] = 0x7fffffff;  //int 最大值: 0x7fffffff
        max_index++;
        sort(b, b + n, greater<int>());
    }
  /**最差 只排序一次的算法
  sort(b,b+n);
  int max_sum=0,max_temp=b[n-1];
  for (int i=n-2;i>=0;i--)
  {
  max_temp+=b[i];
  max_sum=max_sum+max_temp-1;
  }

  */

    cout << max_sum << " " << min_sum << endl;

    return 0;
}

4.算法时间及空间复杂度分析(要有分析过程)

时间复杂度:直接进行排序是O(n*logn),计算min_sum要进行n次排序,所以为O(n^2logn)。

空间复杂度:两个数组的大小,O(n)。

5.心得体会(对本次实践收获及疑惑进行总结)

  实验时,觉得这题很难,需要用到二路归并排序,由于时间限制就直接放弃此题。实际上,三题难度相差不大,由于自己没有仔细看完、审清题目,而出现了“这题很难”的判断,同时也突出了自己对于二路归并排序算法的不熟悉,显露的自己没有发现的弱点。此外,通过此题,对于 functional 头文件内函数功能,有了一定的了解和掌握。  

1.实践题目

4-3 最优合并问题 (100 分)

题目来源:王晓东《算法设计与分析》

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

输入样例:

4

5 12 11 2

输出样例:

78 52

 

2.问题描述

将几个序列合并成一个序列,序列的比较次数的计算方式是序列长度分别为m和n的序列为m+n-1 次。序列的最差合并顺序就是先合并长的再合并短的,序列的最优合并顺序应优先合并最短的。

3.算法描述

Min_sum=(2+5-1)+(2+5+11-1)+(2+5+11+12-1)=52

Max_sum=(12+11-1)+(12+11+5-1)+(12+11+5+2-1)=78

计算最优合并顺序,先将序列长度进行升序排序,合并最短的两个序列,用min_sum记录比较次数,min_sum=a[min_index]+a[min_index+1]-1,用a[min_index]存放合并之后的那个序列,同时将a[min_index+1]置为0,min_index++;再重新排序得到新的列表。(重新排序的原因是因为合并之后的序列有可能比原先的序列都大,这个有点类似哈夫曼树)。以上重复n-1次。

计算最差合并顺序则与上类同。(另附:最差有只排序一次的算法)

复制代码
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;

int main()
{
    int n;
    cin >> n;
    int a[n], b[n], i = 0;
    while(i < n)
    {
        cin >> a[i];
        b[i] = a[i];
        i++;
    }

    //最小
    sort(a, a + n, less<int>());
    int min_index = 0, min_sum = 0;
    while(min_index < n-1)
    {
        min_sum = min_sum + a[min_index] + a[min_index + 1] - 1;
        a[min_index] = a[min_index] + a[min_index + 1];
        a[min_index + 1] = 0;
        min_index++;
        sort(a, a + n, less<int>());
    }

    //最大
    sort(b, b + n, greater<int>());
    //for(int i = 0; i < n; i ++) cout << b[i] << " "; cout << endl;
    int max_index = 0, max_sum = 0;
    while(max_index < n - 1)
    {
        max_sum = max_sum + b[max_index] + b[max_index + 1] - 1;
        b[max_index] = b[max_index] + b[max_index + 1];
        b[max_index + 1] = 0x7fffffff;  //int 最大值: 0x7fffffff
        max_index++;
        sort(b, b + n, greater<int>());
    }
  /**最差 只排序一次的算法
  sort(b,b+n);
  int max_sum=0,max_temp=b[n-1];
  for (int i=n-2;i>=0;i--)
  {
  max_temp+=b[i];
  max_sum=max_sum+max_temp-1;
  }

  */

    cout << max_sum << " " << min_sum << endl;

    return 0;
}

4.算法时间及空间复杂度分析(要有分析过程)

时间复杂度:直接进行排序是O(n*logn),计算min_sum要进行n次排序,所以为O(n^2logn)。

空间复杂度:两个数组的大小,O(n)。

5.心得体会(对本次实践收获及疑惑进行总结)

  实验时,觉得这题很难,需要用到二路归并排序,由于时间限制就直接放弃此题。实际上,三题难度相差不大,由于自己没有仔细看完、审清题目,而出现了“这题很难”的判断,同时也突出了自己对于二路归并排序算法的不熟悉,显露的自己没有发现的弱点。此外,通过此题,对于 functional 头文件内函数功能,有了一定的了解和掌握。  

猜你喜欢

转载自www.cnblogs.com/bigghost/p/11872166.html