哈夫曼树
哈夫曼树的定义:设二叉树具有 n 个带权值的叶节点,那么从根节点到各个叶节点的路径长度与相应叶节点权值的乘积的和,叫作二叉树的带权路径长度 WPL (Weighted Path Length)。具有最小带权路径长度的二叉树称为哈夫曼树 (Huffman Tree),也称为最优二叉树。权值较大的结点离根较近。
构造哈夫曼树的原则(贪心思想):
- 权值越大的叶节点越靠近根节点
- 权值越小的叶节点越远离根节点
哈夫曼编码
哈夫曼编码就是规定哈夫曼树中的左分支为 0,右分支为 1,从根节点到每个叶节点所经过的分支对应的 0 和 1 组成的序列便为该节点对应字符的编码。这样的编码称为哈夫曼编码。
哈夫曼编码其实就是哈夫曼树的一个非常重要的应用,是可变字长编码 (VLC) 的一种,目的是为了减少存储体积。
如何减少存储体积呢?举个例子:一篇文档只包含字母 A、B、C、D、E、F,它们的出现次数为:A 30次,B 25次,C 20次,D 10次,E 10次,F 5次 。
在数据传送时,信息表现为 0 和 1 的二进制比特流形式。如果每个字符都是定长编码,由于总共有 6 中字母,则每个字母最少使用 3 bit 表示,最终对应编码如下:
字符 | 编码 |
---|
A | 000 | B | 001 | C | 010 | D | 011 | E | 100 | F | 101 |
存储空间大小计算:(30 + 25 + 20 + 10 + 10 + 5) * 3 = 300 bit。
我们知道,网络数据传输时,传输数据越大,就越消耗网络的带宽。为了提高传输的速度,可以采用变长的编码方式,寻找更优的编码方式。我们其实可以按照字符出现的概率分配码长,实现平均码长最短的编码。也就是说,设计编码可以考虑让出现多的字符编码尽量更短,出现少的字符编码稍微长点没关系,是一种贪心思想。这样就能使得存储空间大小降低,提高传输速度。而哈夫曼编码算法正是用来解决该问题的。
但是,你需要考虑的一个问题是,二进制开始 0,1,01,10,11 这个顺序 ,如果来了 001 这个编码,它到底是 (0,0,1) 还是 (0,01) 呢?所以编码不等长的时候你要考虑到这个编码要有唯一性不能出现歧义。这个怎么搞呢?计算机只知道 01 二进制,而二叉树刚好有左右两个节点,至于一个字符它如果是对应叶子节点,那么就可以直接确定,也就是说这个数值不能映射到二叉树的非叶子节点上。
具体的编码过程是:
- 初始化 n 个字符单节点的树,每个字符具有概率,记为权重。
- 找到权重最小的两个树,把它们作为新树的左右子树,权重之和作为新树的根节点的权重。
- 重复第 2 步直到剩下一棵单独的树。
- 左子树的一边标 0,右子树一边标 1,从根节点到叶子节点的路径就是哈夫曼编码。
对应哈夫曼编码如下表:
字符 | 编码 |
---|
A | 00 | B | 01 | C | 10 | D | 110 | E | 1110 | F | 1111 |
存储空间大小计算:2*30 + 2*25 + 2*20 + 3*10 + 4*10 + 4*5 = 240 bit
哈夫曼(霍夫曼)编码是一种无前缀编码。解码时不会混淆。其主要应用在数据压缩,加密解密等场合。
|