首页 > 编程语言 >贪心算法-Huffman树

贪心算法-Huffman树

时间:2023-08-31 23:00:29浏览次数:40  
标签:个点 哈夫曼 合并 最小 算法 heap 权值 Huffman 贪心

贪心算法-Huffman树

1. 哈并果子问题的概述及案例

    https://www.acwing.com/problem/content/150/

img

    上图为本问题的案例。
    实际上,本题就是霍夫曼树的应用。关于霍夫曼树的定义,这里就不再赘述。

img

    根据上图,实际上这道题就是在询问:将所有的果子堆进行合并,构造成一颗树之后(最终合并为一堆之后),如何使得总消耗(带权路径之和)最小?很明显,哈夫曼树就可以保证带权路径之和最小。我们只需要将这些果子堆构成一颗哈夫曼树即可。

2. 合并果子问题的步骤

    1.  每次从容器中选择两个最小权值的堆,进行合并。将合并之后的堆放回到容器中。
    2.  重复上述过程,直到容器中只剩一堆为止。
    很明显,上述的过程实际上就是在构造哈夫曼树的过程。

3. 合并果子问题的证明

img

    这道题的证明,本质上就是对哈夫曼树进行证明。
        哈夫曼树的特点就是:每次选取最小的两个点进行合并,这样所得到的一定是最优解。因此,最小的两个点一定深度最深。
        1.  现在我们证明:最小的两个点,深度一定最深且可以互为兄弟。我们在这里采用反证法:最小的两个点深度不是最深。假设,a,f点是最小的两个点。a点位于最后一层(n),f点位于n-1层。(具体树的形状见上图)。当我们将f点与b点进行替换之后,权值一定降低。因此,当最小的两个点深度不是最深时,一定不是最优解。因此,最小的两个点,深度一定最深且可以互为兄弟。
        2.  当我们将n个点进行合并时,我们一定会将权值最小的两个点进行合并。此时还剩n-1个点。我们将从n个点合并成为1个点的某个具体方案记为f(n)。为了求出最优方案,显然每一个f(n)在第一步的时候,都需要将两个权值最小的点进行合并。因此:f(n) = f(n-1) + a + b;(其中,a和b是n个点中权值最小的两个点)。由于,每一个f(n)都会有一个固定常数a+b。因此在求出最佳方案时,我们可以将每一个f(n)后面的a+b去掉。若如此做,并不会影响最佳方案的求解。因此,我们将f(n)的计算变成了f(n-1)的计算。
        3.  对于n-1个点,我们也可以采用上述的方式进行计算。这样就由:f(n-1)的计算转换成了f(n-2)的计算。
        4.  一直进行下去,当从2个点合并成为1个点之后,所得到的解就是全局最优解。

4. 合并果子问题的代码

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

int n;

priority_queue<int,vector<int>,greater<int>> heap;



int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int a;
        scanf("%d",&a);
        heap.push(a);
    }
    int res = 0;
    while(heap.size() > 1){
        int a = heap.top();
        heap.pop();
        int b = heap.top();
        heap.pop();
        res += (a+b);
        heap.push(a+b);
    }
    printf("%d",res);
    return 0;
}

标签:个点,哈夫曼,合并,最小,算法,heap,权值,Huffman,贪心
From: https://www.cnblogs.com/gao79135/p/17656645.html

相关文章

  • [6]-代码随想录算法训练营-dat7-哈希表-part2
    代码随想录算法训练营第七天|哈希表-part21.LeetCode454.四数相加II题目https://leetcode.cn/problems/4sum-ii/submissions/思路无刷随想录后想法将四数相加转化为两数之和借用unordered_map,利用两数之和思想解决本问题实现困难代码尚模糊,不过整个......
  • KMP算法--解决字符串匹配问题--模式串是否在文本串出现过
    KMP算法--解决字符串匹配问题--模式串是否在文本串出现过*利用之前判断过的信息,通过next数组保存最长公共子序列的长度*搜索词/模式串移动的位数=已匹配的字符数-对应的部分匹配值在韩的例子里ABCDABD初次匹配匹配了ABCDAB6位,对应2,所以移动6-2=4位e.g.文本串aabaabaaf......
  • 文心一言 VS 讯飞星火 VS chatgpt (84)-- 算法导论8.2 1题
    一、用go语言,参照图8-2的方法,说明COUNTING-SORT在数组A=(6,0,2,0,1,3,4,6,1,3,2)上的操作过程。文心一言:CountingSort是一种非比较型整数排序算法,适用于一定范围内的整数排序。它的基本思想是,对每一个输入元素x,确定小于x的元素个数,从而确定x在输出数组中的位置。下面是使用Go......
  • Kafka - 生产者 - 压缩算法
    总结1.Producer端压缩、Broker端保持、Consumer端解压缩。2.开启压缩的最佳实践:Producer端完成的压缩,那么启用压缩的一个条件就是Producer程序运行机器上的CPU资源要很充足。如果你的环境中带宽资源有限,那么我也建议你开启压缩。如果你的机器CPU资源有很多富余,强烈......
  • 【CF1374E1】Reading Books (easy version)(贪心)
    题目大意:给出\(n(1\len\le2\times10^{5})\)个三元组\((t,a,b)(0\lea,b\le1)\),选出其中任意个,使得被选中的元素\(a\)、\(b\)的总和均为\(k\),求\(t\)总和的最小值因为被选中的元素\(a\)、\(b\)的总和均为\(k\),所以被选中的三元组中,形式为\((t,1,0)\)和\((t,0,1)\)的数量相等......
  • 新增!视频智能分析/AI算法智能分析网关V5告警功能添加教程来咯!
    智能分析网关系列是基于边缘AI计算技术,可对前端摄像头采集的视频流进行实时检测分析,能对监控画面中的人、车、物进行识别,可实现的检测包括:人脸检测与识别、车辆检测与识别、烟火识别、安全帽/反光衣识别、区域入侵识别等,支持对检测到的异常进行实时告警、抓拍、推送。近期,智能分析......
  • 贪心笔记
    本文主要以例题讲解和贪心方法入手。邻项交换当我们确定操作顺序,并按照题意模拟即可得出答案,就要用邻项交换的办法来确定最优的操作顺序。接水问题对于一个排队顺序\(T_1\simT_n\),答案显然等于:\[\frac{\sum_{i=1}^{n}{(n-i)\timesT_i}}{n}\]那么将其中的\(T_2,T_3\)......
  • 【校招VIP】前端算法考点之快慢指针题型
    考点介绍:链表是校招面试里手撕代码出现频度比较高的题型,三线和中小厂会考察简单的链表反转,大厂会进一步考察复杂度和双指针问题,比如中间元素、是否存在环等。一、考点题目1.一个长度为n的单向链表,用O(1)空间复杂度来实现倒转输出,使用最低时间复杂度解答:单向链表,直接设结点No......
  • 进程调度的原理和算法探析
    进程的调度进程的调度是由操作系统完成的,其目的是为了在一个进程占用CPU执行自己的操作后,选择下一个进程来占用CPU。调度发生的原因很简单,每个进程都希望能够占用CPU进行工作。因此,调度程序会进行上下文切换,并选择一个进程来执行其功能。那么,什么时候进行调度呢?调度的原则又是什......
  • 8.29晚-三板模-弹簧的算法
       ......