C++ 图 的延展 哈夫曼树(四十三)【第九篇】

今天我们来讲一下哈夫曼树

1.哈夫曼树搭建

现在给你这样一个问题:

一棵二叉树上有 n 个叶子结点,每个叶子结点都有一个权值。现在要构造一棵二叉树,树上每条边的权值都是 1,并满足所有 叶子结点权值 和 它到根的 距离的 积 之和sum 最小。

你需要把这棵二叉树画出来:

C++ 图 的延展 哈夫曼树(四十三)【第九篇】_第1张图片

sum=1×2+2×2+3×1=9

思考一下这棵二叉树怎么建立?

我们先看这样一棵二叉树:

C++ 图 的延展 哈夫曼树(四十三)【第九篇】_第2张图片

将所有叶子结点权值与它到根的距离的积之和的计算方法转换为计算每条边的贡献,再求和(如右图)。

根据二叉树的性质:
n[0]=2+1,此时还需要求出 n[1] 的值,就可以确定整棵二叉树的结点数量了。因为将问题转换为边权的贡献和,所以需要尽量让边的数量更少,因此 
n[1]=0。

这是因为度数为 
1 的点只会不会影响叶子结点的数量。

C++ 图 的延展 哈夫曼树(四十三)【第九篇】_第3张图片

因此这样二叉树中结点的数量有n=n[0]+n[2]=2n[0]−1;边的数量有 2n[0]−1。

根据上图的右侧图中可以发现每条边的贡献实际上是该边连接的“下侧”结点的权值,而对于一个非叶子结点的权值是等于它的两个儿子结点的权值和。

现在我们的目的就是让每个结点的权值(边的贡献)尽可能小,因为最初给的均为叶子结点的权值,所以从叶子结点开始构造。

将所有的叶子结点看作一棵子树,每棵子树的权值为该树根结点的权值,利用贪心思想:

  1. 每次选择两棵权值最小的子树,新建一个结点向两棵子树的根结点连边,合成一棵新的子树,新子树的权值为两棵子树的权值和;

  2. 不断进行 (1) 操作,如果只剩下一棵子树的时候,结束。

最终非叶子节点的权值和就等于这棵树的 sum。

你可能感兴趣的:(C++,数据结构,算法)