概述
赫夫曼树一般指哈夫曼树,给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为赫夫曼树(Huffman Tree)。
赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
应用
1.赫夫曼编码(详情见另一篇博客 赫夫曼编码
构造原理
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的赫夫曼树。
代码实现
节点类
public class Node implements Comparable<Node>{
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return this.value - o.value; //整体添加负号表示从大到小排序
}
@Override
public String toString() {
//重写toString方法,只显示value值
return "Node [value=" + value + "]";
}
public int getDate() {
// TODO Auto-generated method stub
return this.value;
}
}
mian:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestHuffmanTree {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {3,7,8,29,5,11,23,12};
Node node = creatHuffmanTree(arr);
System.out.println(node); //打印出根结点(最小根)
}
//创建赫夫曼树
public static Node creatHuffmanTree(int[] arr) {
//使用数组中的所有元素创建若干个二叉树(只有一个结点)
List<Node> nodes = new ArrayList<>(); //创建二叉树集合
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.getDate() + right.getDate());
parent.left = left;
parent.right = right;
//把取出来的两个二叉树移除
nodes.remove(left);
nodes.remove(right);
//将新二叉树放入原来的二叉树集合中
nodes.add(parent);
}
return nodes.get(0);
}
}