定义:给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树
路径: 从一个节点到另一个节点的分支构成
路径长度: 从树中某个节点到另一个节点之间的分支数目
权: 树中节点相关的数值
带权路径长度: 从根开始,从根开始,路径长度 * 权值;
树的带权路径长度: 树中所有叶节点的带权路径长度之和成为该树的带权路径长度
哈夫曼树: 带权路径最小的树
构成赫夫曼树的步骤
1.从小到大排序,将每一个数据,每个数据都是一个节点,每个节点可以看成是一个最简单的二叉树
2.取出根节点权值最小的两颗二叉树
3.组成一颗新的二叉树,该新的二叉树的根节点是前面两颗二叉树根节点权值之和
4.再将这颗新的二叉树,以根节点的权值大小,再次排序,不断重复 1-2-3- 4的步骤,直到数列众所有的数据都被处理掉,就得到一颗赫夫曼树。
图示
1.对这些散树排序
1>
5>
package mzy.tree_b;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class HuffmanTree {
public static void main(String[] args) {
int[] arr = { 13, 7, 8, 3, 29, 6, 1 };
NumNode resnNode = creHTree(arr);
preOrder(resnNode);
// 前序遍历
}
// 前序遍历
public static void preOrder(NumNode root) {
if (root != null) {
root.preOder();
} else {
System.out.println("根节点为空!");
}
}
// 创建赫夫曼树
public static NumNode creHTree(int[] arr) {
// 为了操作方便
// 1.遍历数组
// 2.将arr的每一个元素构建成一个NumNode
// 3.将NumNode放入到ArrayList中
List<NumNode> nodes = new ArrayList<NumNode>();
for (int value : arr) {
nodes.add(new NumNode(value));
}
Collections.sort(nodes);
System.out.println("paixi:" + nodes);
// 取出权值最小的二叉树
while (nodes.size() != 1) {
// 排序从小到大
Collections.sort(nodes);
// 取出权值最小的值左右值
NumNode leftNode = nodes.get(0);
NumNode rightNode = nodes.get(1);
// 构建一颗二叉树
NumNode parent = new NumNode(leftNode.value + rightNode.value);
parent.Nleft = leftNode;
parent.Nright = rightNode;
// 删除集合里的二叉树
nodes.remove(leftNode);
nodes.remove(rightNode);
// 将新节点放进集合里
nodes.add(parent);
}
System.out.println("paixi:" + nodes);
return nodes.get(0);
}
}
//创建节点类
class NumNode implements Comparable<NumNode> {
int value;// 节点
NumNode Nleft;// 左子节点
NumNode Nright;// 右子节点
public NumNode(int value) {
this.value = value;
}
public String toString() {
return "NumNode [value=" + value + "]";
}
public int compareTo(NumNode n) {
// 表示从小到达排序
return this.value - n.value;
}
public void preOder() {
System.out.println(this);
if (this.Nleft != null) {
this.Nleft.preOder();
}
if (this.Nright != null) {
this.Nright.preOder();
}
}
}