c语言-最优合并问题

问题描述:
给定k个排好序的序列s1,s2,…,sk,用2路合并算法将这k个序列合并成一个序列。假设采用的2路合并算法合并2个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
算法设计:
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
数据输入:
由文件input.txt给出输入数据。第1行有1个正整数k,表示有k个待合并序列。接下来的1行中,有k个正整数,表示k个待合并序列的长度。
结果输出:
将计算的最多比较次数和最少比较次数输出到文件output.txt。

输入文件示例 输出文件示例
input.txt output.txt
4 78 52
5 12 11 2

设计思路:
由题目已知得合并长度为m和n需要比较次数为m+n-1,要想得到最优合并顺序,根据贪心算法的思想,局部最优即全局最优,先考虑长度最短的两个数进行合并,合并后的数字加入数组中然后再次挑选长度最短的两个数合并,一直到将所有数据合并完为止。
首先用一个数组存储要合并的序列,如果要求最优合并,则升序排列,每次合并后的数字替代合并前的第二个数字,然后对后面的再次排序,重复前面的步骤。如果是最差情况,则降序排列,从最大的开始,每次挑选最大的两个数字合并,合并后的数字加入原数组,再排序然后合并。
因为采用的c语言,所以排序的时候用的c语言标准库中的qsort函数,qsort函数执行效率还是比较低的,如果数据量不大可以,如果数据量较大还是用c++中的sort函数比较好。或者只进行一次排序,其他时候可以二分查找找出合并后的函数插入位置,虽然算法看起来复杂了一些,但是执行效率却提高了。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

//升序
int cmp1(const void* a, const void* b)
{
    return *(int*)a - *(int*)b; 
}

//降序
int cmp2(const void* a, const void* b)
{
    return *(int*)b - *(int*)a;
}

//最优情况
int getMin(int* a, int n)
{ 
    int min = 0;
    for (int i = 0; i < n - 1; i++)
    { 
        qsort(a + i, n-i,sizeof(int),&cmp1);	//升序 
        a[i + 1] += a[i];	//更改数据 
        min += a[i + 1] - 1;
    }
    printf("最优情况min=%d\n", min);
	return min;
}


//最差情况 
int getMax(int* b, int n)
{
    int max = 0;
    for (int i = 0; i < n - 1; i++)
    {
        qsort(b + i, n - 1, sizeof(int), &cmp2);//降序 
        b[i + 1] += b[i];
        max += b[i + 1] - 1;
    }
    printf("最差情况max=%d\n", max);
	return max;
}
int main()
{
    int a[100], b[100];
    int n;

	//读取数据
    FILE* f1 = fopen("D:/学习/大三上/算法设计与分析/实验三报告+附件/input.TXT","r");
    if (f1 == NULL)
    {
        printf("文件打开失败");
            return 0;
    }
    fscanf(f1,"%d", &n);
    printf("要合并的序列为:");
    for (int i = 0; i < n; i++)
    {
        fscanf(f1,"%d", &a[i]);
		printf("%3d", a[i]);
        b[i] = a[i];
    }
	printf("\n");
	fclose(f1);

	//输出数据
    int min = getMin(a, n);
    int max = getMax(b, n);
	FILE*f2 = fopen("D:/学习/大三上/算法设计与分析/实验三报告+附件/output.TXT", "w");
	fprintf(f2, "%3d,%3d", min, max);
	fclose(f2);
    return 0;
}

运行结果:
在这里插入图片描述

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值