赫夫曼树
一.介绍:
1)给定n个权(每个节点的值)作为n个叶子节点,构造一颗二叉树,若该树的带权路径长度(wpl)达到最小,称这样的树为最优二叉树,也称哈夫曼树或者霍夫曼树
2)赫夫曼树是带权路径长度最短的树,权值较大的节点离根较近
二.概念:
1)路径和路径长度:在一棵数中,从一个节点往下可以达到的孩子或者孙子节点之间的通路,成为路径.通路中分支的数目称为路径长度.若规定根节点的层数为1,则从根节点到L层节点的路径长度为L-1
2)节点的全及带权路径长度:若将树中节点赋给一个有着某种含义的数值,则这个数值称为该节点的权,节点的带权路径长度:从根节点到该节点之间的路径长度与该节点的路径权的乘积
3)树的带权路径长度:树的带权路径长度规定为所有叶子节点的带权路径长度之和,记为wpl,权值越大的节点离根节点越近的二叉树才是最优二叉树
4)WPL最小的就是赫夫曼树
三.构成赫夫曼树思路
当给定一个数组时,要求转成赫夫曼树
思路:
1)先将数组按照从小到大排序,将每个值看成节点的权
2)取出两个最小的值组成最简单的二叉树
3)将这二叉树的和当做一个新的权值然后与数组中的其他数组成二叉树,重复以上步骤
代码块
public class HaffmanTree {
public static void main(String[] args) {
int[] arr = {3, 5, 2, 6, 23, 13};
Node huffmanTree=createHaffmanTree(arr);
preOrder(huffmanTree);
}
//前序遍历方法
public static void preOrder(Node root){
if (root == null){
System.out.println("赫夫曼树为空");
}
root.preList();
}
/**
*
* @param arr 需要创建的赫夫曼树
* @return 赫夫曼树的头结点
*/
public static Node createHaffmanTree(int[] arr) {
//第一步创建根据数组创建node对象
//1.遍历arr数组
//2.将arr的每个元素构成一个node
//3.将node放入一个ArrayL中
ArrayList<Node> nodes = new ArrayList<>();
for (int value : arr) {
nodes.add(new Node(value));
}
//排序 从小到大
// Collections.sort(nodes);
// System.out.println(nodes.get(0));
// System.out.println(nodes.get(1));
// System.out.println(nodes);
while (nodes.size() > 1) {
//排序 从小到大
Collections.sort(nodes);
// System.out.println(nodes);
//取出前两个数,构造成一个二叉树
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parentNode = new Node(leftNode.value + rightNode.value);
parentNode.left = leftNode;
parentNode.right = rightNode;
//在yuanlist中删除节点并添加新节点
nodes.remove(rightNode);
nodes.remove(leftNode);
nodes.add(parentNode);
}
//取出HaffmanTree的头结点
return nodes.get(0);
}
}
//创建节点类
//为了让node对象支持排序Collection集合排序
//让node实现Collectable接口
class Node implements Comparable<Node> {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
//表示从小到大排序
return this.value - o.value;
}
//前序遍历
public void preList(){
System.out.println(this);
if (this.left!= null){
this.left.preList();
}
if (this.right!= null){
this.right.preList();
}
}
}