当前位置: 编码机 >> 编码机发展 >> 原以为哈夫曼树哈夫曼编码很难,结果大佬
哈夫曼树、哈夫曼编码很多人可能听过,但是可能并没有认真学习了解,今天这篇就比较详细的讲一下哈夫曼树。
首先哈夫曼树是什么?
哈夫曼树的定义:给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(HuffmanT),哈夫曼树是带权路径长度最短的树。权值较大的结点离根较近。
那这个树长啥样子呢?例如开始2,3,6,8,9权值节点构成的哈夫曼树是这样的:
从定义和图上你也可以发现下面的规律:
初始节点都在树的叶子节点上权值大的节点离根更近每个非叶子节点都有两个孩子(因为我们自下向上构造,两个孩子构成一个新树的根节点)
你可能会好奇这么一个哈夫曼树是怎么构造的,其实它是按照一个贪心思想和规则构造,而构造出来的这个树的权值最小。这个规则下面会具体讲解。
哈夫曼树非常重要的一点:WPL(树的所有叶结点的带权路径长度之和)。至于为什么按照哈夫曼树方法构造得到的权重最小,这里不进行证明,但是你从局部来看(三个节点)也要权值大的在上一层WPL才更低。
WPL计算方法:WPL=求和(Wi*Li)其中Wi是第i个节点的权值(valu)。Li是第i个节点的长(深)度.
例如上面2,3,6,8,9权值节点构成的哈夫曼树的WPL计算为(设根为第0层):
比如上述哈夫曼树的WPL为:2*3+3*3+6*2+8*2+9*2=(2+3)*3+(6+8+9)*2=61.
既然了解了哈夫曼树的一些概念和WPL的计算方式,下面看看哈夫曼树的具体构造方式吧!
哈夫曼树构造
初始给一个森林有n个节点。我们主要使用贪心的思想来完成哈夫曼树的构造:
在n个节点找到两个最小权值节点(根),两个为叶子结构构建一棵新树(根节点权值为左右孩子权值和)先删掉两个最小节点(n-2)个,然后加入构建的新节点(n-1)个重复上面操作,一直到所有节点都被处理
在具体实现上,找到最小两个节点需要排序操作,我们来看看2,6,8,9,3权值节点构成哈夫曼树的过程。
初始时候各个节点独立,先将其排序(这里使用优先队列),然后选两个最小节点(抛出)生成一个新的节点,再将其加入优先队列中,此次操作完成后优先队列中有5,6,8,9节点
重复上面操作,这次结束队列中有11,8,9节点(排序后8,9,11)
如果队列为空,那么返回节点,并且这个节点为整个哈夫曼树根节点root。
否则继续加入队列进行排序。重复上述操作,直到队列为空。
在计算带权路径长度WPL的时候,需要重新计算高度(从下往上),因为哈夫曼树是从下往上构造的,并没有以常量维护高度,可以构造好然后计算高度。
具体代码实现(仅供参考)
importjava.util.ArrayDqu;importjava.util.ArrayList;importjava.util.Comparator;importjava.util.List;importjava.util.PriorityQuu;importjava.util.Quu;publicclassHuffmanT{publicstaticclassnod{intvalu;nodlft;nodright;intdp;//记录深度publicnod(intvalu){this.valu=valu;this.dp=0;}publicnod(nodn1,nodn2,intvalu){this.lft=n1;this.right=n2;this.valu=valu;}}privatnodroot;//最后生成的根节点Listnodnods;publicHuffmanT(){this.nods=null;}publicHuffmanT(Listnodnods){this.nods=nods;}publicvoidcatT(){Quunodq1=nwPriorityQuunod(nwComparatornod(){publicint
转载请注明:http://www.aideyishus.com/lktp/3694.html