要想了解哈夫曼树(最优二叉树,或赫夫曼树),先要了解以下概念:
路径:从树中一个结点到另一个结点之间的分支构成两个结点之间 的路径;路径长度:路径上的分支数目。就是从一个结点到另一个结点有多少个路径;结点的路径长度:从根到该结点的路径长度;树的路径长度:从树根到每一个结点的路径长度之和;结点的权:在一些应用中,赋予树中结点的一个有某种意义实数;结点的带权路径长度:从根结点到该结点的路径长度与相应结点权值的乘积。树的带权路径长度:所有叶结点的带权路径长度之和;哈夫曼树是带权路径长度最短的树。
一般步骤:
先对权值结点列表进行排序(从小到大);取出权值最小的两个结点,小的为左孩子,大的为右孩子,和作为父节点,从结点列表中删除这两个结点,并将父结点作为新的结点加入结点列表中;重复以上步骤,直到集合中只剩一个元素。举个例子: 对于权值结点列表{60, 45, 13, 69, 14, 5, 3}
步骤一:排序{3, 5, 13, 14, 45, 60, 69}
步骤二:
排序:
构造父结点:
排序:
构造父结点、排序:
构造父结点:
向左分支为 0,向右分支为 1,从根到叶子的路径构成叶子的哈夫曼编码(前缀编码)。 如上述例子中的:{ A:60, B:45, C:13 D:69 E:14 F:5 G:3},假设权值表示每种字符出现的频率 加上0、1编码后:
则每个字符的二进制编码为:
A:10 B:01 C:0011 D:11 E:000 F:00101 G:00100
比如想传送BCD时,编码为:01001111 通过观察,哈夫曼树的它的字母都在叶子结点上,因此不会出现一个字母的编码为另一个字母编码左起子串的情况,可以避免编码冲突(编码冲突:一个字母的二进制代表数,为另一个字母的二进制代表数的子串)。 哈夫曼树的构造并不是唯一的,但带权路径长度都是最小的。 例如:{3, 5, 7, 8,14 },可以有以下两种构造形式。