概念
什么是哈夫曼树
总结起来就是要满足两个条件:
- 二叉树
- 带权路径长度最小
带权路径长度
带权的结点的带权的路径长度为从该结点到树根之间的路径长度与结点上权的乘积。树的带权路径长度(WPL)为树中所有叶子结点的带权路径长度之和。
例如下面的二叉树,有5个带权结点,它WPL= 5×3+15×3+40×2+30×2+10×2=220
构造哈夫曼树
构造哈夫曼树,即构造一个带权路径长度最小的二叉树。
假如这棵树的带权结点分别为:10、5、30、15、40。我们可以使用下面方法来构造一颗哈夫曼树。
1、先把有权值的叶子结点按照从小到大的顺序排列成一个有序序列:5、10、15、30、40
2、取头两个最小权值的结点作为一个新节点的两个子结点,注意相对较小的是左孩子。新结点的权值为两个叶子权值的和5+10=15。
3、将序列中的5、10
替换为15
。此时序列为15、15、30、40
。然后重复步骤2。
4、将序列中的15、15
替换为30
。此时序列为30、30、40
。再次重复步骤2。
5、将序列中的30、30
替换为60
。此时序列为40、60
。再次重复步骤2,哈夫曼树就构建成功了。
此时的哈夫曼树带权路径长度WPL=40×1+30×2+15×3+10×4+5×4=205
哈夫曼编码
普通方式编码
假如我们有一段文字内容为“BADCADFEED”要网络传输给别人,显然用二进制的数字(0和1)来对内容进行编码。我们现在这段文字只有六个字母ABCDEF,那么我们可以用相应的二进制数据表示。
字母 | 二进制字符 |
---|---|
A | 000 |
B | 001 |
C | 010 |
D | 011 |
E | 100 |
F | 101 |
这样我们编码之后的数据为:001000011010000011101100100011
如果一篇文章很长,这样的二进制串也将非常的可怕。而且事实上,不管是英文、中文或是其他语言,字母或汉字的出现频率是不相同的,比如英语中的几个元音字母“a e i o u”,中文中的“的 了 有 在”等汉字都是频率极高。假设这几个字母出现的频率是A 27,B 8,C 15,D 15,E 30,F 5
,我们使用普通编码方式就不能达到一个好的效果。
哈夫曼编码
我们可以把每个字母出现的频率当做哈夫曼树的带权结点,进行构造哈夫曼树。
此时,我们将向左的路径标为0,向右的路径标为1。对这六个字母用其从树根到叶子所经过路径的0或1来编码,
这个时候就可以得到每个字母的二进制编码:
原编码二进制串:001000011010000011101100100011
(共30个字符)
新编码二进制串:1001010010101001000111100
(共25个字符)
可以看出哈夫曼编码节约了很大一部分存储和传输成本。
参考资料:《大话数据结构》——程杰