数据结构之树-哈夫曼树-学习笔记-59

引入

上一节我们发现,树、森林和二叉树之间竟然有这么多有趣的关联,前根和后根遍历结果竟然都可以跟二叉树相同。二叉树竟然这么的独特,今天我们就来看看,如何打造一棵完美二叉树!

从一个问题出发

我们在使用二叉树的时候,会遇到类似这样的问题

  • 这是一棵二叉树,结点连接线上的数字,是访问这个结点的概率
  • 我们有5%的几率访问 A、15%访问 B、70%访问 C、10%访问 D
  • 那么问题来了,既然绝大多数都是访问 C 的
  • 那访问 C 必须要先判断是否是 A 或者 B,这样太麻烦了

要弄清楚这个问题,我先首先要弄清楚刚才哪些加了数字的结点是什么。

带权叶子结点

还是这张图,我们看到这棵二叉树有一点点不同

  • 结点前有一个数值,我们把这种结点间连线的相关书叫做权。
  • 我们管这些叶子结点,叫做带权叶子结点。
  • 数值越大,权重越大。

结点的路径长度


我们引申出一个新定义,结点的路径长度,我们来看一下

结点的路径长度

定义:根结点到叶子结点的路径上的连接数。

上图中,C 结点的路径长度为 3。

  • 根到右子树,为1
  • 右子树到右子树为,为2
  • 右子树到右子树的左子树 C ,为3

树的路径长度

定义:根到每一个结点的路径长度之和。

上图中,我们来算一下

  • 根到 A 是1
  • 根到 B 是2
  • 根到 C 是3
  • 根到 D 是3
  • 所以$1+2+3+3=9$
  • 上面这棵树的路径长度为9。

结点带权路径长度

结点的路径长度是根到结点,那么带上权呢?

定义:结点的路径长度与结点权值的乘积。

我们还是拿 C 结点举例

  • C 结点的路径长度我们算过了,长度是 3
  • 那么 C 结点的带权路径长度就是$3 \times 70=210$
  • C 结点的带权路径长度为210

树的带权路径长度

定义:根到每一个结点的路径长度乘以权值的和。

上图中,我们来算一下

  • 根到 A 是1,权值是5,$1 \times 5=5$
  • 根到 B 是2,权值是15,$2 \times 15=30$
  • 根到 C 是3,权值是70,$3 \times 70=210$
  • 根到 D 是3,权值是10,$3 \times 10=30$
  • 所以$5+30+210+30=275$
  • 上面这棵树的带权路径长度为275。

我们将树的带权路径长度称为 WPL(Weighted Path Length)
记住,WPL 就是树中所有叶子结点的带权路径长度之和。

最优二叉树

我们称 WPL 的值越小,构造出来的二叉树就约优秀,那么该如何构造出最优的二叉树呢?对了,最优二叉树我们也称为哈夫曼树!

初始化

首先,我们在森林中选择两课根结点权值最小的树,上图所示

  • 我们把 A B C D 看做四棵树组成的森林
  • A B C D 就是四个根节点,四个根节点都有一个权值
  • 我们把最小的两个提取出来,即 C 和 D

接着我们来操作上面的两个最小的结点

  • 把两个结点中权值较小的放到左边,即 C 放到左边,作为左孩子
  • 权值较大的结点放在右边,作为右子树
  • 将左右子树的权值相加,得到6,作为左右子树的双亲结点,我们记作N1

继续添加


我们剩下的还有两个结点,A 和 B

  • 上一步我们得到了一个 N1,权值是 C D 的和
  • 此时我们从 A 和 B 中选择一个较小的结点 B,拿出来


我们开始比较 B 和 N1

  • 如果 B 比 N1 大,那就放右边作为右子树,反之作为左子树
  • 因为 B 是5,N1是6,所以我们把 B 放在左边
  • 同样的生成一个 N2,N2的权值是 N1和 B 的和,即5+6=11


最后剩下的结点 A 相同,最后得到这棵哈夫曼树的根权值为18。
哈夫曼树构造完毕。

哈夫曼树的优点?

我们费劲儿构建的这棵哈夫曼树有什么厉害的地方呢?

  • WPL 最小,WPL 还记得吧?就是树的带权路径
  • 我们不可能构建出比哈夫曼树更好的排列方式
  • 所以我们将哈夫曼树也成为完美二叉树。

回到问题


还记得我们开头这个问题吗?既然访问节点的概率就是权值的话,我们用哈夫曼树的构建方式,将 A B C D 重新构建之后,就可以解决啦!

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。


-------------The End-------------
欢迎请我喝咖啡哦~!