给定N个权值作为N个叶子节点,构造一个二叉树,带权路径长度总和最小,这样二叉树称做哈夫曼树,又称做最优二叉树。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
哈夫曼编码
数据通信中,需要将传输的文字转为二进制的字符串,为了使编码后字符串尽可能端,在不等长编码中,可以让使用频率高的字符用短码,频率低的字符使用长码。
为了使不等长编码为前缀编码(要求一个字符的编码不能是另一个字符的编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。
哈夫曼树
假如对于字符a,b,c,d,e,f,g的权重分别是3,24,6,20,34,4,12。则对应的哈夫曼树如下图:
根据上边的哈夫曼树,可以得到个字符对应的编码为:
a:10110
b:01
c:1010
d:00
e:11
f:10111
g:100
建树思路
- 每次选取所有叶子节点中权重最小的两个节点,组成一棵子树;
- 移除原有的两个节点
- 将新生成的子树插入序列中
- 重复上述步骤,直到集合中只有一个节点
生成树结构
// 节点对象
private class Node implements Comparable<Node>{
private T data;
// 权重
int weight;
Node parent, left, right;
public Node(T data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(@NotNull Node o