赫夫曼树
基本介绍:
给定n个权值作为n个叶子节点, 构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树,哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
重要概念:
-
路径和路径长度:在一棵树中,从一个节点往下可以达到孩子或者孙子节点直接的通路叫做路径。通路中分支的数目称为路径长度。若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L - 1
-
节点的权及带权路径长度:若将树中节点赋给一个有着某种含义的数值,则这个数值称为该节点的权,节点的带权路径长度为:从根节点到该节点之间路径长度 X 该点的权值。
-
所有叶子节点的带权路径长度之和称为树的带权路径长度WPL,
-
WPL 最小的就是赫夫曼树。
赫夫曼树的构造:
给定数组 [5,29,7,8,14,23,3,11]
构成赫夫曼树的步骤:
- 将数组从小到大进行排序,创建节点类,将这些值作为节点的权值。储存在集合里。
- 取出权值最小的两个节点,并创建一个新的节点作为这两个节点的父节点,这个父节点的权值为两个子节点之和。将这两个节点分别赋给父节点的左右节点。
- 删除这两个节点,将父节点添加进集合里。
- 重复第二步到第四步,直到集合中只剩一个元素,结束循环。
代码实现:
private static Node huffman(int[] arr) {
//创建一个集合存储二叉数
List<Node> nodes=new ArrayList<Node>();
for (int value:arr){
nodes.add(new Node(value));
}
while (nodes.size()>1) {
//对集合进行排序
Collections.sort(nodes);
//取出最小的节点
Node left=nodes.get(nodes.size()-1);
//取出次小的节点
Node right=nodes.get(nodes.size()-2);
//新建一个根节点
Node parent=new Node(left.value+right.value);
parent.left=left;
parent.right=right;
//删除两个节点
nodes.remove(left);
nodes.remove(right);
//将根节点添加进集合中
nodes.add(parent);
}
return nodes.get(0);
}