huffman编码的java实现
实现思路
1. 对于存储在list中的node节点按照权重(weight)进行升序排序,然后反复取出两个最小权重的节点a1、a2,生成一个父节点b分别指向这两个节b.setleftchild(a1),b.setRightchild(a2)。将b插入集合中,再次排序。此处过程使用堆来反复删除与排序。最终生成huffman树
2. 对Huffman树进行前序遍历,记录每次走过的过程,然后获得Huffman编码。
* 代码实现 *
创建Huffman树
/**
* 构建Huffman树
* @param nodes 存储node的链表
* @return root节点
*/
public static <T> Node<T> createTree(List<Node<T>> nodes) {
//priorityQueue 选择最小的元素放在堆头
Queue<Node<T>> queue = new PriorityQueue<Node<T>>(nodes.size(),
new Comparator<Node<T>>() {
@Override
public int compare(Node<T> o1, Node<T> o2) {
if (o1.getWeight() > o2.getWeight())
return 1;
else if (o1.getWeight() < o2.getWeight())
return -1;
return 0;
}
});
for (Node<T> node : nodes) {
queue.add(node);
}
while (queue.size() > 1) {
Node<T> left = queue.poll();
Node<T> right = queue.poll();
Node<T> parent = new Node<T>(null, left.getWeight()
+ right.getWeight());
parent.setLeft(left);
parent.setRight(right);
queue.add(parent);
}
return queue.poll();
}
获得huffman编码
/**
*
* @param root huffman root节点
* @return map 存储对应节点的huffmancode
*/
public static <T> Map<T,int[]> getHuffmanCode(Node<T> root){
Map<T,int[]> map=new HashMap<T,int[]>();
int[] codes=new int[128];
getHuffmanCode(root,0,codes,map);
return map;
}
private static <T> void getHuffmanCode(Node<T> root,int index,int[] code,Map<T,int[]> map){
if (root.isLeaf()) {
int[] mycode=new int[index];
for(int i=0;i<index;++i){
mycode[i]=code[i];
}
map.put(root.getData(), mycode);
return;
}
else{
if(root.getLeft()!=null){
code[index++]=0;
getHuffmanCode(root.getLeft(), index, code, map);
index--;
}
if(root.getRight()!=null){
code[index++]=1;
getHuffmanCode(root.getRight(), index, code, map);
index--;
}
}
}
测试代码
public static void main(String[] args) { List<Node<String>> list = new ArrayList<Node<String>>(); list.add(new Node<String>("a",8)); list.add(new Node<String>("b",7)); list.add(new Node<String>("c",6)); list.add(new Node<String>("d",5)); list.add(new Node<String>("c",1)); Node<String> root = HuffmanTree.createTree(list); Map<String,int[]> map=HuffmanTree.getHuffmanCode(root); for(Map.Entry<String, int[]> entry:map.entrySet()){ System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue())); } }
测试结果
g:[0, 1, 0] d:[0, 1, 1] b:[1, 0] c:[0, 0] a:[1, 1]