数据结构之哈夫曼树
现在,我们经常会使用压缩和解压缩软件来处理文档,因为它除了可以减少文档在磁盘上的空间外,还有重要的一点,就是我们可以在网络上一压缩的形式传输大量数据,是的保存和传递都更加高效。
那么压缩而不出错是如何做到的呢?简单说,就是把我们要压缩的文本进行重新编码,今天我们就介绍一种最基本的压缩编码方法——哈夫曼编码。
在介绍哈夫曼编码之前,我们必须的介绍哈夫曼 树,首先,我们来看一个例子:
现在,有的课程,老师通常会按照以下方法,将学生的成绩将其分为不及格,及格,中等,良好和优秀这样的等级。
但是,如果在实际生活中,学生的成绩在5个等级上的分布规律如下:
那么70分以上约占总数80%的成绩都需要经过3次以上的判断才可以得到结果,这显然不合理。
如是,我们根据上面的比例对这颗二叉树进行重新分配,改成如下结果:
效率应该更高一些,但是到底高多少,以及这颗二叉树是如何设计的,我们来看看这个过程,也就是哈夫曼树的构造过程。
哈夫曼树定义与原理
我们先把上面两棵树简化成叶子结点带权的二叉树,如下图所示,其中A表示不及格,B表示及格,C表示中等,D表示良好,E表示优秀。
那么,从上图我们可以得到几个概念:
(1)路径长度:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径长度,例如二叉树a中,根节点到结点D的路径长度为4.
(2)树的路径长度:指从树根到每一个结点的路径长度之和。例如二叉树a的路径长度就是1+1+2+2+3+3+4+4=20.
(3)带权路径长度:结点的带权路径长度为从该节点到树根之间的路径长度与结点上权的乘积。
(4)树的带权路径长度:树中所有叶子结点的带权路径长度之和,例如二叉树a的带权路径长度为:5*1+15*2+40*3+30*4+10*4=315.
(5)哈夫曼树:指带权路径长度最小的二叉树为哈夫曼树。
哈夫曼树的构造过程及算法如下:
因此,上述成绩的哈夫曼树的构造过程为下:
.........
哈夫曼编码
如果我们想要有一段文字内容“BADCADFEED”,通过网络传输给别人,显然用二进制的数字(0和1)来表示是很自然的想法,因此,我们可以用相应的二进制数据表示:
那么要传输的数据编码以后为“0010000011010000011101100100011”,共30个字符。
但是,在英文中每个字母出现的频率是不一样的,例如“a e i o u”几个元音字母出现频率很高,那么我们完全可是使用哈夫曼树来重新规划他们,假如六个字母出现的频率为A 27,B 8,C 15,D 15,E 30, F 5.那么我们可以构造如下的哈夫曼树:
在上图中,我们将权值左分支改为0,右分支改为1。得到如下的哈夫曼树:
我们对这六个字母用其从树根到叶子所经过的路径的0和1来编码,可以得到如下所示的定义:
我们对“BADCADFEED”再次编码为“1001010010101001000111100”,共17个字符,因此节约了17%的传输成本。