霍夫曼树基本概念:
路径:从一个结点往下到孩子或孙子结点之间的同理
路径长度:如结点1到结点7的路径长度=2
结点的权:将结点的某一属性值作为结点的权
带权路径长度:从根节点到该结点*该结点的权;如结点1到结点7的带权路径长度:7*2=14
的带权路径长度(WPL):该树的所有叶子结点的带权路径长度之和
霍夫曼树:给定n个权值,构造一颗二叉树并由这n个权值作为数的叶子结点,且该树的带权路径长度(WPL)达最小,这样的二叉树成为最优二叉树,也叫霍夫曼树
霍夫曼树特点:权值越大的叶子结点离根节点越近
霍夫曼编码:
编码规则:
(1)给定一个字符串,统计各个字符出现的次数,将次数作为权值构成霍夫曼树;例如“i like like like java do you like a java”转化为霍夫曼树为:
(2)规定路径向左为0,向右为1,则各个权值的路径即为他们的霍夫曼编码
注意:
(1)霍夫曼编码为前缀编码,即任何编码不会是其他编码的前缀(因为叶子结点)
(2)若出现权值相同的结点,则根据排序方法不同,对应的霍夫曼编码也不完全相同,但压缩率是相同的。
代码实现:
以“i like like like java do you like a java”为例
结点
class ByteNode implements Comparable<ByteNode> {
Byte data;//存放字符本身,注意用包装类方便存入集合中
int weight;//权值,表示字符出现的次数
ByteNode left;
ByteNode right;
public ByteNode(Byte data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(ByteNode o) {
return this.weight - o.weight;
}
@Override
public String toString() {
return "ByteNode{" +
"data=" + data +
", weight=" + weight +
'}';
}
//前序遍历
public void preOrder() {
System.out.println(this);
if (this.left != null)
this.left.preOrder();
if (this.right != null)
this.right.preOrder();
}
}
字符串->生成结点并放入List中
private static