基本概念
权:赋予某个实体一个量,是对该实体的某个或某些属性的数值化描述。在数据结构中,实体有节点与边两大类,因此对应的有节点权与边权。简单理解就是:为节点或边赋予一个数值。
节点的带权路径长度:从该结点到树根之间的路径长度乘以节点上的权的积。
树的带权路径长度:所有叶子节点的带权路径长度之和。通常记作WPL。
哈夫曼树:WPL最小的二叉树称为哈夫曼树。
哈夫曼编码:在哈夫曼树中,每一个叶子节点都有唯一的路径,该路径中左分支记0,右分支记1,那么可将该路径用01表示,这一串01便是哈夫曼编码。
构建
由哈夫曼树的定义可知,权越大,其离根节点应该越近。因此,可按如下步骤进行构建。
1,将每一个权值构建成一个棵树——该树只有根节点。
2,选取两棵根结点权值最小的树作为左右子树构建一棵新的二叉树,并且新树根节点的权值为两棵子树权值之和。
3,将2中选取的权值删除,并将新生成的权值添加到权值列表中。
4,重复2,3两个步骤,只到权值列表中只有一个权值。此时得到的二叉树并是哈夫曼树。代码如下:
private static List<Node> huffmanTree(List<Node> nodes) {//nodes是按value值从小到大排序好的
while (true) {//使用死循环,会一直循环到
if (nodes.size() == 1) {//只有一个节点,哈夫曼树已经生成
return nodes;
}
Node first = nodes.remove(0);//因为nodes排序过,所以直接取两个Node就是权值最小的节点
Node second = nodes.remove(0);
Node parent = new Node(first.value + second.value);//生成父节点
first.parent = parent;
second.parent = parent;
parent.lchild = first;
parent.rchild = second;
insert(nodes, parent);//将父节点插入到nodes中
}
}
private static void insert(List<Node> src, Node node) {
for (int x = 0; x < src.size(); x++) {
if (src.get(x).value > node.value) {
src.add(x, node);
return;
}
}
src.add(node);
}