Huffman树、霍夫曼编码
Huffman树指的是带权路径长度WPL最小的二叉树
WPL=路径*权值
Huffman常用于压缩编码,正常传输ABCDEF这些字母需要3位二进制树来描述,但由于一篇文章中ABCDEF这些字母出现的概率不同,用较多的二进制位数表示出现概率低的字母,而用较少的二进制位数表示概率高的字母。
Huffman编码实现:
package HuffmanTree; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import javax.xml.crypto.Data; //Huffman树压缩 public class HuffmanTree<T>{ public static Map<Object, String> map=new HashMap<Object,String>(); //创建Huffman树 public static <T> Node<T> createTree(List<Node<T>> nodes) { while (nodes.size() > 1) { 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.getWeight() + right.getWeight()); parent.setLeft(left); parent.setRight(right); nodes.remove(left); nodes.remove(right); nodes.add(parent); } return nodes.get(0); } //保存Huffman树 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()) { 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; } //编码 public static<T> void encoding(Node<T> node,String str) { if(node==null) { return; } if(node.getLeft()==null&&node.getRight()==null) { // System.out.println(node.getData()+":"+str); map.put(node.getData(),str); return; } encoding(node.getLeft(), str+"0"); encoding(node.getRight(), str+"1"); } } //二叉树结点 class Node <T> implements Comparable<Node<T>>{ private T data; private int weight; private Node<T> left; private Node<T> right; public Node(T data, int weight) { this.data = data; this.weight = weight; } @Override public String toString() { // TODO Auto-generated method stub return "data:" + this.data + ",weight:" + this.weight + "; "; } @Override public int compareTo(Node<T> o) { // TODO Auto-generated method stub if (o.weight > this.weight) { return 1; } else if (o.weight < this.weight) { return -1; } return 0; } public T getData() { return data; } public void setData(T data) { this.data = data; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } 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; } }
测试:
package HuffmanTree; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class App { public static void main(String[] args) { // TODO Auto-generated method stub List<Node<String>> nodes = new ArrayList<Node<String>>(); nodes.add(new Node<String>("A", 27)); nodes.add(new Node<String>("B", 8)); nodes.add(new Node<String>("C", 15)); nodes.add(new Node<String>("D", 15)); nodes.add(new Node<String>("E", 30)); nodes.add(new Node<String>("F", 5)); Node<String> root = HuffmanTree.createTree(nodes); HuffmanTree<String> h=new HuffmanTree<String>(); h.encoding(root, ""); Iterator<Entry<Object, String>> entries = HuffmanTree.map.entrySet().iterator(); String string=""; while (entries.hasNext()) { Entry<Object, String> entry = entries.next(); string+=entry.getValue(); System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } System.out.println("ABCDEF的编码为:"+string); } }
结果:
Key = A, Value = 01 Key = B, Value = 1001 Key = C, Value = 00 Key = D, Value = 101 Key = E, Value = 11 Key = F, Value = 1000 ABCDEF的编码为:01100100101111000