本篇 核心知识点 :哈夫曼树(最优二叉树)全套概念、构造流程、WPL 计算
一、哈夫曼树(最优二叉树)
1 基础专业概念
(1)路径
概念:树中任意两个节点之间唯一的通路;
特性:二叉树两点有且仅有一条连通路径,无环路。
(2)路径长度
概念:路径上经过节点的数量;每经过一个节点,路径长度 + 1。
(3)节点权值
概念:给叶子节点赋予代表使用频率、权重的数值;只有叶子带权,中间节点无业务权值。
(4)带权路径长度 WPL
概念:单个叶子节点 路径长度 × 自身权值;整棵树 WPL = 所有叶子带权路径之和。
(5)哈夫曼树(最优二叉树)
概念:给定一组叶子权值,构造出整树 WPL 最小的二叉树,称为哈夫曼树。
特性:
-
哈夫曼树形态不唯一,但所有合法构造的 WPL 一定相等;
-
不存在度为 1 的节点,所有中间节点度均为 2;
-
应用场景:文件数据压缩编码(哈夫曼编码)。
2 哈夫曼树标准构造步骤
-
将所有权值作为独立叶子节点,存入有序容器(升序排列);
-
取出当前权值最小的两个节点,作为新节点的左右子树;
-
新节点权值 = 两个子节点权值之和;
-
删除刚才取出的两个最小节点,将新生成的父节点放回容器重新排序;
-
重复 2~4 步,直到容器仅剩余 1 个节点,该节点为哈夫曼树根。
3 构造示例 + WPL 计算
给定权值数组 {2,2,3,4,5}
-
首轮最小 2、2 → 新节点 4,剩余
{3,4,5,4} -
次轮最小 3、4 → 新节点 7,剩余
{4,5,7} -
次轮最小 4、5 → 新节点 9,剩余
{7,9} -
最后 7、9 合并根 16
WPL 计算:
2×3 + 2×3 + 3×2 + 4×2 + 5×2 = 6+6+6+8+10 = 36
拓展特性
不同合并顺序会生成形态不同哈夫曼树,但全局 WPL 数值完全一致。
4 代码框架(哈夫曼树节点)
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
int main(){
unordered_map<string, int> equip;
// 下标插入,键不存在自动创建
equip["长剑"] = 120;
// insert插入,重复键无效
equip.insert(pair<string,int>("法杖",95));
// 遍历
for(auto& item : equip)
cout << item.first << " 攻击:" << item.second << endl;
// 查找
if(equip.find("长剑") != equip.end())
cout << "武器存在" << endl;
return 0;
}