一、什么是哈夫曼树
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
二、哈夫曼树特点
哈夫曼树的特点:
-
没有度为1的结点(每个非叶子结点都是由两个最小值的结点构成)
n个叶子结点的哈夫曼树总共有2n-1个结点 -
n0:叶结点总数
n1:只有一个儿子的结点总数 n2:有2个儿子的结点总数 n2=n0-1
N=n0+n1+n2=2n-1 -
哈夫曼树的任意非叶结点的左右子树交换后仍是哈夫曼树;
-
对同一组权值{w1,w2,…},存在不同构的两个哈夫曼树,但是它们的总权值相等。
三、图的解析过程
- 第一步,给定一些数值,例如 : 1、4、8、16、32、64
2、找到最小的两个值,将他们的和构成一个新的节点
3、接下来就拿次小的数和刚刚组合出来的新节点,在重新组合,这样一次类推。
4、
5、
6、最后就形成了这样的一颗哈夫曼树,这也是二叉树的前序
四、代码实现
public class Node<T> implements Comparable<Node<T>> {
private T data;
private int height;
private Node<T> left;
private Node<T> right;
public Node(T data, int height) {
this.data = data;
this.height = height;
}
@Override
public String toString() {
return "Node:" + this.height;
}
@Override
public int compareTo(Node<T> o) {
if (o.height > this.height) {
return 1;
} else if (o.height < this.height) {
return -1;
}
return 0;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getLeft() {
return left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return right;
}
public void setRight(Node<T> right) {
this.right = right;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class HuffmanTree<T> {
public static <T> Node<T> createTree(List<Node<T>> nodes) {
while (nodes.size() > 1) {
// 这里直接用Java8已有的方法 sort排序
// 但这个需要对应的实体类实现Comparable接口,重写compareTo自定规则比较
Collections.sort(nodes);
Node<T> left = nodes.get(nodes.size() - 1);
Node<T> right = nodes.get(nodes.size() - 2);
// 这里就是哈夫曼树的特点: 他的两个叶子节点之和等于他的父节点
Node<T> parent = new Node<T>(null, left.getHeight()
+ right.getHeight());
parent.setLeft(left);
parent.setRight(right);
//删除原先两个权值最小的节点二叉树
nodes.remove(left);
nodes.remove(right);
// 再添加最新的这个节点
nodes.add(parent);
}
return nodes.get(0);
}
public static <T> List<Node<T>> breath(Node<T> root) {
List<Node<T>> list = new ArrayList<Node<T>>();
Queue<Node<T>> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
// 这里就是利用Queue队列里的方法,移除第一个元素
Node<T> pNode = queue.poll();
list.add(pNode);
if (pNode.getLeft() != null) {
queue.add(pNode.getLeft());
}
if (pNode.getRight() != null) {
queue.add(pNode.getRight());
}
}
return list;
}
}
```java
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main(String[] args) {
List<Node<String>> nodes = new ArrayList<Node<String>>();
nodes.add(new Node<String>("a", 1));
nodes.add(new Node<String>("b", 4));
nodes.add(new Node<String>("d", 16));
nodes.add(new Node<String>("c", 8));
nodes.add(new Node<String>("f", 64));
nodes.add(new Node<String>("e", 32));
Node<String> root = HuffmanTree.createTree(nodes);
System.out.println(HuffmanTree.breath(root));
}
}