目录
哈夫曼树通常以二叉树的形式出现,采用贪心算法的思想。
二叉树:每个节点仅有两个子节点,举个栗子,如下图:
不过这并不是哈夫曼树,这只是一棵平平无奇的二叉树。真正的哈夫曼树请听我娓娓道来。
哈夫曼树的构造
若我们已知结点的权值的集合为(5,19,21,2,3,6,7,10,32,14,52),我们该如何构造他的哈夫曼树呢?
我们可以有如下步骤:
- 找到当前权值集合中最小的两个权值并将其相加,构成新的权值。
- 将新的权值放入集合中,重复第一步,直到所有的权值都已经使用过了。
那么对于上面我们提到的这个集合,按照我们的两步走策略我们不难得出以下解题思路:
PS:最终的效果图我会在讲解完思路后给出
- 首先找出两个最小的权值2和3,我们先画在草稿纸上,并将其相加,得出一个新的权值5,将5分别与2和3相连,同时将集合中的2和3用5替换,得到新的集合为(5,19,21,5,6,7,10,32,14,52)。
- 在新的集合(5,19,21,5,6,7,10,32,14)中,我们找出最小的两个权值是5和5
(没错,不是我写重复了,就是这样),加入已经构造好的哈夫曼树,得到新的权值10并把两个5用10替换,得到(19,21,10,6,7,10,32,14,52)。注意,为了最终构造完成的哈夫曼树更加整洁规范,我们一般把小的数字写在左边,大的写在右边。 - 在(19,21,10,6,7,10,32,14,52)中找出最小的两个权值6和7,加入构造好的哈夫曼树,得到新的权值13并替换6和7。
- 在(19,21,10,13,10,32,14,52)中找出最小的两个权值10和10,加入哈夫曼树,得到新的权值20并替换两个10。
- 在(19,21,20,13,32,14,52)中找出最小的两个权值13和14,加入哈夫曼树,得到新的权值27并替换13和14。
- 在(19,21,20,27,32,52)中找出最小的两个权值19和20,加入哈夫曼树,得到新的权值39并替换19和20。
- 在(21,39,27,32,52)中找出最小的两个权值21和27,加入哈夫曼树,得到新的权值48并替换21和27。
- 在(39,48,32,52)中找出最小的两个权值39和32,加入哈夫曼树,得到新的权值71并替换39和32。
- 在(71,48,52)中找出最小的两个权值48和52,加入哈夫曼树,得到新的权值100并替换48和52。
- 此时我们终于来到最后一步,在(71,100)中找出最小的两个
(然而就剩两个了)权值71和100,加入哈夫曼树,得到新的权值171,此时我们就只剩一个权值,完成树后即结束构造。
最终的效果图如下:
那么讲完哈夫曼树的构造,哈夫曼编码又是什么?
哈夫曼编码
哈夫曼编码简单来讲可以用8个字来记忆:左零右一,按路查询。每个节点与左孩子的路径标为0,与右孩子的路径标为1,得出如下图:
那么此时如果我们要求结点6的哈夫曼编码,我们就从根结点171出发,一直朝着结点6的方向出发,这个过程有点像DFS一直走到底的“特性”,走到6后我们就会得出它的哈夫曼编码为10100。原理是从根结点171出发到结点6时,我们经过171-100,100-48,48-27,27-13,13-6共5条路径,这路条路径的“编码”分别为1,0,1,0,0,因此我们可以得到6的哈夫曼编码为10100。
同理如果我们要求结点32的哈夫曼编码,我们则可以从171出发,走到32,得出结点32的哈夫曼编码为00。其他的结点求解方法相同。
但是在实际做题中,一般一个结点会对应一个字母或其他物品,如下图,他们的原理一致。
在这题中,唯一有所区别的是我们在文章中讲的是权值,这题中用到的是频率,其实质一样,我们假设共有100个字符,那么每个字母出现的次数就为(7,19,2,6,32,3,21,10),这个集合一出现,是否又眼熟起来了?
今天对哈夫曼树及其编码的讲解就到这里,如果对您有所帮助,希望您可以为我留下一个点赞和关注,这对我真的很重要,谢谢!