哈夫曼编码(1)哈夫曼编码的基本概念及应用【c++】和哈夫曼树算法的基本思想


哈夫曼编码这个词相信大家都不陌生,它是一种给字符编码的工具,发明他的人是美国的哈夫曼大叔,这个编码是用来压缩文件的,他要满足的是:

1.每个字符的编码中只含数字0,1;

2.每一个字符的编码都不是另一个字符的前缀(这样才保证输入的编码无歧义)

3.尽可能保证数量少(公式:每一个字符的频率*编码长度之和)

为了更好地满足这三个条件,我们创造出了一个以树和集合为基础的算法,就叫哈夫曼算法;

哈夫曼算法先是定义多个子树,有多少个字符就定义多少个树,这些树刚开始时都存于一个集合中,每一步把当前森林中频率最小的两棵子树合并为一棵子树 ,原始树作为子节点或子树,他的父亲的权值就是两个子节点的权值和,这可子树只能是二叉树,这一棵新树也存放与集合中,并代替掉了刚刚的两棵子树,这棵新树的频率就是那两棵子树的频率和…以此类推,重复操作。最后得到的树一定满足每个非叶节点恰好有两个子节点(因为编码只有0和1).

下面是此树的构造过程

在这里插入图片描述

注意:每两个子树合并为一个时,一定要添加父节点,不能直接将其中一个子树作为其父节点。

构造出树后,我们把每一条边都标上数值,保证每一个非叶节点的两个儿子的边有一个是0.有一个是1,这样才不会出现重复。

哈夫曼编码的计算过程:

刚才说了,我们要尽可能让哈夫曼编码的值小,这也是为什么要用最小的权值子树作为子树,这样可以让深度越深的字符权值越小,那么,哈夫曼编码的计算过程为:每个字符权值*长度之和。

应用:

[NOI2015] 荷马史诗

题目背景

追逐影子的人,自己就是影子 —— 荷马

题目描述

Allison 最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》 组成的鸿篇巨制《荷马史诗》实在是太长了,Allison 想通过一种编码方式使得它变得短一些。

一部《荷马史诗》中有 nnn 种不同的单词,从 111nnn 进行编号。其中第 iii 种单词出现的总次数为 wiw_iwi。Allison 想要用 kkk 进制串 sis_isi 来替换第 iii 种单词,使得其满足如下要求:

对于任意的 1≤i,j≤n1\leq i, j\leq n1i,jni≠ji\ne ji=j ,都有:sis_isi 不是 sjs_jsj 的前缀。

现在 Allison 想要知道,如何选择 sis_isi,才能使替换以后得到的新的《荷马史诗》长度最小。在确保总长度最小的情况下,Allison 还想知道最长的 sis_isi 的最短长度是多少?

一个字符串被称为 kkk 进制字符串,当且仅当它的每个字符是 000k−1k-1k1 之间(包括 000k−1k-1k1 )的整数。

字符串 str1str1str1 被称为字符串 str2str2str2 的前缀,当且仅当:存在 1≤t≤m1 \leq t\leq m1tm ,使得 str1=str2[1..t]str1 = str2[1..t]str1=str2[1..t]。其中,mmm 是字符串 str2str2str2 的长度,str2[1..t]str2[1..t]str2[1..t] 表示 str2str2str2 的前 ttt 个字符组成的字符串。

输入格式

输入的第 111 行包含 222 个正整数 n,kn, kn,k ,中间用单个空格隔开,表示共有 nnn 种单词,需要使用 kkk 进制字符串进行替换。

接下来 nnn 行,第 i+1i + 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

来自八中的小鹿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值