数据结构之二叉树的哈夫曼树及其应用

前面一篇介绍的是,二叉树的一些基本概念、特征以及它如何同树、森林转换之类,现在介绍的,二叉树的另外一类,哈夫曼二叉树树。
哈夫曼树(Huffman)树,又称最优树,是一类带权路径长度最短的树,有着广泛的应用(哈夫曼树,并不针对只是二叉树,其他的树也可以是哈夫曼,只要满足是带权路径最小即可),在这里只讨论哈夫曼树的二叉树。

相关概念:
——树的每一层,到下一层的路径距离,统一记为 1 。 树中的一个结点到另一个结点的路径,是由这两个结点之间的分支所构成的,路径上分支数目,称为是它的路径长度(对于树来说,结点间的路径是唯一的了,所以路径长度也就是唯一的了,但是对于图来说,两个结点的路径就不是唯一的了,路径长度也就不唯一了)。
——树的路径长度,是从树的根结点,到树的每一个结点的路径长度之和,称为 PL。经过计算,完全二叉树具有最小到的二叉树路径(易见,因为完全二叉树的结点都是先布满一层再到下一层,所以在相同的结点数目下,其叶子结点最少,路径长度之和最小)。

哈夫曼二叉树:
哈夫曼二叉树,,是带权(Weight)的二叉树。这个权,不是指一层到下一层的距离加成,而是每一个结点会有权值,权是在路径的终点(记为Wi),而不是在路径之中。带权路径长度是两个结点的距离,才乘以终点结点的权的乘积。
n 个叶子的二叉树的带权路径长度定义是,WPL = Wi x li 的和(i = 0,1,2……n)。在带权的二叉树中,其 WPL 值最小的二叉树,称为最优二叉树,即是哈夫曼二叉树。
不过值得一提的是,对于带权的二叉树,权都是放在了叶子结点,对于还有子结点的那些结点,是只作为中间结点,不设置权的。如果真的要计算其权值的话,就是其子结点的权值之和。

如何构建哈夫曼树:
将构成森林 F 的树,按照权值从小到大排列,将最小的两个相加起来创建一个结点,这两个结点就作为它的子结点,并将新的结点放进去从小到大排列(那两个最小的结点就不要进入序列里了)。循环这么做,直到最后,只有一个结点,即是哈夫曼二叉树了。
如下:
数据结构之二叉树的哈夫曼树及其应用
哈夫曼编码:
哈夫曼树在数据编码中的一个应用,就是数据的最小冗余编码问题(求一段字符串按照怎么样的编码方式来实现映射出来的二进制位数最少)。
对于“ABCD”这样的字段,如果用二进制编码它,首先要确定的是,每个字符用二进制怎么表示,有以下解决方案:
每个字符都用固定长度的位数来表示,如用 00 、01 、10 、11,这样子就是 00011011。但是 A 用两个位来表示,浪费了。
每个字符不用固定长度的位数来表示,如用 0 、1 、01 、11,这样子就是 0011011这样子 。但是怎么知道 01 是 ‘0’ 和 ‘1’,还是“01”呢 ?这种情况的问题在于,如果需要编码的对象太多了,如何避免歧义?

而哈夫曼编码提出的方案是,先确定这个字符串的各元素的出现频率,这就是对应了哈夫曼二叉树的权值,根据权值大小,对它们进行排列,构建二叉树。这样子每个元素在二叉树里都有对应的地址(可知,通过构建哈夫曼二叉树的办法,那些元素都是到了叶子的位置)。如果设置每个结点的左子树,为 0 ,右子树为 1 。则每个元素都有一个编码了。而那些路径就是对应的元素的编码位数。可见,出现频率越高的,离根结点的距离越近,所以它所占用编码位数越少。而只要构建好了这样的二叉树,从二进制数解码为字符串的过程不过就是遍历地址得到元素的过程(思路很巧妙呀)。
虽然这样子需要每一个字符串都设置一个哈夫曼二叉树,但是如果已经有一个程序来做的话,这样的过程并不复杂。
上面关于哈夫曼编码的过程,可见
https://www.cnblogs.com/kubixuesheng/p/4397798.html
链接里配图了,很详细。