Huffman编码为字母分配编码,代码长度取决于对应的字母的相对使用频率或者“权”,因此它是一种变长编码。每个字母的Huffman编码是从称为Huffman编码树或简称Huffman树的满二叉树中得到。Huffman树中每个叶子结点对应一个字母,叶结点的权重就是它对应字母的出现频率。其目的在于按照最小外部权重建立一棵树。
首先,定义一个Huffman结点的接口,以反映Huffman树结点所应有的信息
package huffTree;
public interface HuffNode {
//每个结点的权重
public int weight();
//是否是叶子结点
public boolean isLeaf();
//左子树
public HuffNode left();
//生成左子树
public void setLeft(HuffNode hn);
//该结点的右子树
public HuffNode right();
//生成该结点的右子树
public void setRight(HuffNode hn);
}
定义一个元素和频率相对应的类
package huffTree;
public class FreqPair {
private Object it;
private int freq;
public FreqPair(Object it,int freq)
{
this.it = it;
this.freq = freq;
}
public int weight()
{
return freq;
}
Object val()
{
return it;
}
}
因为叶子结点和内部结点包含不同的信息,所以可以分开实现它们
叶子结点
package huffTree;
public class LeafNode implements HuffNode {
private FreqPair it;
public LeafNode(Object obj,int freq)
{
it = new FreqPair(obj,freq);
}
FreqPair val()
{
return it;
}
@Override
public int weight() {
return it.weight();
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public HuffNode left() {
return null;
}
@Override
public void setLeft(HuffNode hn) {
}
@Override
public HuffNode right() {
return null;
}
@Override
public void setRight(HuffNode hn) {
}
}
内部结点实现
package huffTree;
public class IntlNode implements HuffNode {
private HuffNode lc;
private HuffNode rc;
private int wgt;
public IntlNode(HuffNode lc,HuffNode rc)
{
wgt = lc.weight() + rc.weight();
this.lc = lc;
this.rc = rc;
}
@Override
public int weight() {
return wgt;
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public HuffNode left() {
return lc;
}
@Override
public void setLeft(HuffNode hn) {
lc = hn;
}
@Override
public HuffNode right() {
return rc;
}
@Override
public void setRight(HuffNode hn) {
rc = hn;
}
}
声明Huffman类
package huffTree;
public class HuffTree {
private HuffNode theRoot;
public HuffTree(Object obj,int freq)
{
theRoot = new LeafNode(obj,freq);
}
public HuffTree(HuffTree lc,HuffTree rc)
{
theRoot = new IntlNode(lc.root(),rc.root());
}
public HuffNode root()
{
return theRoot;
}
public int weight()
{
return theRoot.weight();
}
}
因为在构建Huffman树的时候要排序,我们可以使用TreeSet的排序功能
首先定义一个比较器
package huffTree;
import java.util.Comparator;
public class comparator<HuffTree> implements Comparator<HuffTree> {
@Override
public int compare(HuffTree o1, HuffTree o2) {
return ((huffTree.HuffTree) o1).weight() - ((huffTree.HuffTree) o2).weight() ;
}
}
接着实现BuildHuffTree
package huffTree;
import java.util.TreeSet;
public class BuildHuffTree {
public HuffTree buildTree(TreeSet<HuffTree> ts)
{
HuffTree temp1,temp2,temp3 = null;
for(;ts.size() >= 2;)
{
temp1 = ts.pollFirst();
temp2 = ts.pollFirst();
temp3 = new HuffTree(temp1,temp2);
ts.add(temp3);
}
return temp3;
}
}
初始时,所有元素都是叶结点,所以可以将所有的元素都加入到TreeSet集合类中,然后通过调用buildTree实现构建HuffMan树。