规范哈夫曼编码和Deflate算法

文章介绍了哈夫曼编码的基本原理,以及在处理大字母表时存储编码的挑战。规范哈夫曼编码通过仅存储码字长度和利用字母顺序解决了这个问题。Deflate算法结合了哈夫曼编码的约束,确保码字按字典序排列,从而优化压缩效率。这种方法在处理大量数据时能显著节省存储空间。
摘要由CSDN通过智能技术生成

经过常规的哈夫曼编码以后,我们需要将每个符号对应的码字记录下来,比较容易想到的是按照字母序记录每个字母的编码,这样的好处是字母与码字的映射关系被隐式记录:
假设字母表 A = { a 1 , a 2 , a 3 , a 4 , a 5 } \mathcal{A}=\{a_1,a_2,a_3,a_4,a_5\} A={a1,a2,a3,a4,a5} P ( a 1 ) = P ( a 3 ) = 0.2 P(a_1)=P(a_3)=0.2 P(a1)=P(a3)=0.2 P ( a 2 ) = 0.4 P(a_2)=0.4 P(a2)=0.4 P ( a 4 ) = P ( a 5 ) = 0.1 P(a_4)=P(a_5)=0.1 P(a4)=P(a5)=0.1,构造的哈夫曼树如下:
在这里插入图片描述
每个码字可以由码字的长度后跟码字来表示。因此,编码将存储为 [ 2 , 01 , 1 , 1 , 3 , 000 , 4 , 0010 , 4 , 0011 ] [2, 01, 1, 1, 3, 000, 4, 0010, 4, 0011] [2,01,1,1,3,000,4,0010,4,0011]。这对于小字母表的哈夫曼编码当然是可以管理的,但是当我们的字母表非常大时,它显然会对压缩性能产生影响。

规范哈夫曼编码

规范哈夫曼编码可以大大减少编码的存储需求。在描述如何构建规范哈夫曼编码之前,我们先来看看哈夫曼树的一个属性。考虑下面的一棵哈夫曼树。我们将展示的是,如果我们只从左到右给出树上的码字的长度,就可以重建编码。例如,在这棵树中,长度为 3、4、4、2、1。
在这里插入图片描述
为了通过每个码字的长度重新生成对应的编码,我们从深度为 4(最长码字的长度)的树开始。
在这里插入图片描述
然后我们从左边开始对树剪枝,以匹配码字的长度。我们首先修剪掉最左边的两个分支,留下深度为 3 的叶子。这对应于第一个码字。接下来的两个码字的长度为 4,所以我们将接下来的两个叶子留在深度为 4 的位置。下一个码字的长度为 2,因此我们剪掉所有较低层的分支,留下深度为 2 的叶子。最后,我们对树的右半部分进行剪枝,得到长度为 1 的码字对应的叶子。
在这里插入图片描述

剪枝后的树可以在左分支和右分支上分别填充 0 和 1 来生成编码。从图中我们可以看到码字为 000、0010、0011、01、1。所以,只要知道特定顺序的码字长度就可以重新生成哈夫曼编码。

Deflate 算法

这又带来一个新的问题:我们不知道哪个码字属于哪个字母。规范过程为我们提供了一种生成隐式包含该信息的编码的方法。为了嵌入这些附加信息,我们需要对哈夫曼编码过程进行一些附加约束:

  • 给定长度的所有码字都按字典序连续产生,其顺序与它们所代表的符号相同
  • 较短的码字按字典顺序排在较长的码字前面

我们可以将这些约束合并到哈夫曼编码过程中,或者我们可以使用常规方法生成哈夫曼编码,并转换为规范哈夫曼编码。使用后一种方法更简单。为此,我们将从设计哈夫曼编码开始。从这个设计中,我们将提取码字的长度。我们将使用这些长度和规范约束来设计编码。

还是上面那个例子,字母表 A = { a 1 , a 2 , a 3 , a 4 , a 5 } \mathcal{A}=\{a_1,a_2,a_3,a_4,a_5\} A={a1,a2,a3,a4,a5},哈夫曼码字长度为 { 2 , 1 , 3 , 4 , 4 } \{2,1,3,4,4\} {2,1,3,4,4}。我们从最短到最长的顺序生成码字,记住较短的码字按字典顺序排在较长的码字之前的约束。最短的码字分配给 a 2 a_2 a2。长度为 1 的字典序最小码字为 0,因此 a2 的码字为 0。长度为 2 的码字必须为 1x 形式。只需要一个长度为 2 的代码字,即 a 1 a_1 a1 的码字,因此我们将 10 分配给 a 1 a_1 a1。长度为 3 的代码字现在必须采用 11x 的形式。我们只需要一个长度为 3 的代码字,因此, a 3 a_3 a3 的代码字是 110。有两个长度为 4 的码字, a 4 a_4 a4 a 5 a_5 a5。因此, a 4 a_4 a4 的码字是 1110, a 5 a_5 a5 的码字是 1111。现在可以仅通过发送码字长度来获得码字。与前面的编码方式不同,我们确切地知道哪个代码字属于字母表中的哪个字母,这是因为字典序的限制。

按照先长度后字典序的方法从左到右剪枝。通过查看码字长度列表,我们知道最短的是 a 2 a_2 a2 的码字,因此先剪出长度为 1 的叶子节点并为 a 2 a_2 a2 编码,接下来是 a 1 a_1 a1,等等。 a 4 a_4 a4 a 5 a_5 a5 的码字长度相同,按照字典序先产生 a 4 a_4 a4 的码字。因此,只需对长度列表进行编码就足以存储哈夫曼编码。对于大小为 5 的字母表,这并不是很大的节省;然而,当字母大小为 256 的数量级时,节省的空间会非常可观。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值