本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
数据结构13——哈夫曼树的定义、原理及哈夫曼编码
1 哈夫曼树的定义与原理
在如今素质教育的实际学习生活中,学生的成绩在5个等级上的分布规律如下:
采用传统方法判断学生学习等级如图所示:
那么70分以上大约占总数80%的成绩都需要经过3次以上的判断才可以得到结果,这显然对算力具有很大的浪费。我们对这棵二叉树重新进行分配,改成如图所示的二叉树。
我们把这棵二叉树简化成叶子结点带权的二叉树**(树结点间的边相关的树叫做权【weight】)**,如图所示,其中A表示不及格,B表示及格,C表示中等,D表示良好,E表示优秀。每个叶子的分支线上的数字就是五级分制的成绩所占的百分比。
**从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径长度。**在上图二叉树a中,根结点到结点D的路径长度就为4,第二个二叉树中根结点到结点D的路径长度为2。
**树的路径长度就是从树根到每一结点的路径长度之和。**在上图中,我们可计算出二叉树a的路径长度为,二叉树b的路径长度为
结点的带权的路径长度为从该结点到树根之间的路径长度与结点上权的乘积,其中带权路径长度最小的二叉树称做哈夫曼树。
对上图二叉树a和b两棵树的值:
二叉树a的
二叉树b的
其中5是A结点的权,1是A结点的路径长度。
如果我们现在有10000个学生的百分制成绩需要计算五级分制成绩,用二叉树a的判断方法,需要做31500次比较,而用二叉树b的判断方法,只需要22000次比较。
构造哈夫曼树的哈夫曼算法的描述如下:
- 根据给定的n个权值,构成n棵二叉树的集合,其中每棵二叉树中只有一个带权为的根结点,其左右子树均为空。
- 在中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左右子树上根结点的权值之和。
- 在中删除这两棵树,同时将新得到的二叉树加入中。
- 重复步骤2和3,直到只含一棵树为止。这棵树便为哈夫曼树。
将学生的成绩在5个等级上的分布规律转变成哈夫曼树步骤如下:
-
把有全职的叶子结点按照从小到达的顺序排列成一个有序序列,即
-
取头两个最小权值的结点作为一个新结点的两个子节点,注意相对较小的是左孩子,在这里为的左孩子,为的右孩子,如图所示。新结点的权值为两个叶子权值的和为。
-
将替换A与E,插入有序序列中,保持从小到大排列,即。
-
重复步骤2,将与作为一个新结点的两个子节点,如图所示,的权值=15+15=30。
-
将替换与,插入有序序列中,保持从小到大排列,即。
-
重复步骤2,将与D作为一个新结点的两个子结点,如图所示,的权值=30+30=60。
-
将替换与,插入有序序列中,保持从小到大排列。即。
-
重复步骤2,将与作为一个新结点T的两个子结点,如图所示,由于T是根结点,所以完成哈夫曼树的构造。
左图二叉树的带权路径长度,与有图的原二叉树相比,还少了15,此时构造出的二叉树才是最优的哈夫曼树。
2 哈夫曼编码
哈夫曼树的最大目的是为了解决远距离通信(电报)的数据传输的最优化问题。
比如有一段文字内容“BADCADFEED”要通过网络传输给别人,现在这段文字中出现的六个字母A、B、C、D、E、F的六个字母频率为27,8,15,15,30,5。我们利用哈夫曼树来规划他们。
下图为构造哈夫曼树的过程的权值显示,右图为将权值左分支改为0,右分支改为1后的哈夫曼树。
我们对这六个字母用其从树根到叶子所经过的路径的0或1来编码,可得到如下定义:
我们将文字内容“BADCADFEED”再次编码,对比可发现结果串变小了。
原编码二进制串:001000011010000011101100100011(共30个字符)
新编码二进制串: 1001010010101001000111100(共25个字符)
一般地,设需要编码的字符集为,各个字符在电文中出现的次数或频率集合为,以作为叶子结点,以作为相应叶子结点的权值来构造一棵哈夫曼树。规定哈夫曼树的左分支代表0,右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码,这就是哈夫曼编码。