哈夫曼树与哈夫曼编码

0.什么是哈夫曼树?

哈夫曼树的定义:

0.带权路径长度(WPL):设二叉树有n个叶子节点,每个叶子节点带有权值

,从根节点到每个叶子节点的长度为
,则每个叶子节点的带权路径长度之和就是:
.

1.最优二叉树或哈夫曼树:WPL最小的二叉树。

2.哈夫曼树的由来,就是为了使得平均查找次数最小而衍生出的二叉树。

1.哈夫曼树的构造

0.实现哈夫曼树的方式有很多种,可以使用优先队列(堆/Priority Queue)简单的实现这个过程,给权重较低的符号较高的优先顺序,演算法如下:

0.把n个终端节点加入优先队列保存,则n个节点都有一个优先权Pi,1 <= i <= n

1.如果堆中的节点数大于1,则:

<1>:从堆中移出两个最效地Pi节点,即连续做两次remove(min(Pi),Priority_Queue)

<2>:产生一个新的节点,此节点为<1>移除节点的父节点,而此节点的权重值为<1>两节点权重之和

<3>:把<2>中产生的节点加入到堆中

2.最后在堆中的点为树的根节点 -----算法时间复杂度为:O(nlogn)

1.我们还有跟快的方式使得事件复杂度降至线性时间O(n),就是使用两个队列创建哈夫曼树。第一个队列用来存储n个符号(即n个终端节点)的权重,第二个队列用来存储两两权重的和。此方法可以保证第二个对立的前端(Front)权重永远是最小值,方法如下:

0.把n个终端节点加入第一个队列(按照权重的大小排列,最小的在前端,如果没有顺序则需要排序,时间复杂度就为O(nlogn))

1.如果队列中的节点数大于1,则:

<1>:从队列前端移除两个最低权重的节点

<2>:将<1>中移除的两个节点权重相加合成一个新的节点

<3>:把新的节点加入第二个队列

3.最后在第一个队列的节点为根节点


使用两个队列,从小到大将数组a的元素加入队列fir,队列sec为空。每次我们将两个元素合并,可以证明一定是三种之一。

队列fir中的队首和第二位合并

队列sec中的队首和第二位合并

队列fir中的队首和sec中的队首合并优先考虑合并的两个数的和较小的情况。

将每次合并完的数放入sec队列,直到sec队列只有一个元素,结束算法。 

注意注意:虽然此方法比使用堆保存的事件复杂度还低,但是如果给出的节点并不是按照大小排好顺序的,那么排序就至少花费O(nlogn)的时间。

2.哈夫曼树的有关概念

<0>:路径和路径长度

在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。

<1>:结点的权及带权路径长度

若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。

<2>:树的带权路径长度

树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。

3.代码实现

有点长,不过成就感杠杠的!!!

你可能感兴趣的:(哈夫曼树与哈夫曼编码)