哈夫曼树又叫最优二叉树,是一类带权路径最短的二叉树。哈夫曼树是二叉树的一种应用,在信息检索中很常用。
哈夫曼树可以用来解决报文编码问题,在通信领域有着非常广泛的运用。具体什么是带权路径二叉树,什么是哈夫曼编码这里不做介绍,这里只介绍代码,必须先知道这些概念才能阅读代码!
以下为全部代码,做了比较详细的注释,所以不做另外解释
节点类:
package huffman_binary_tree; //树结点 public class Node { private String data; private Node leftNode; private Node rightNode; //结点的权值 private double weight; public Node(String data,double weight){ this.data=data; this.weight=weight; } public Node getLeftNode() { return leftNode; } public void setLeftNode(Node leftNode) { this.leftNode = leftNode; } public Node getRightNode() { return rightNode; } public void setRightNode(Node rightNode) { this.rightNode = rightNode; } public String getData() { return data; } public void setData(String data) { this.data = data; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } @Override public String toString() { // TODO Auto-generated method stub return "Node[data="+data+",weight="+weight+"]"; } }
package huffman_binary_tree; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; //哈夫曼树 public class HuffmanTree { /** * 节点集合 */ private List<Node> nodes=new ArrayList<Node>(); /** * 添加结点 * @param node * @return */ public HuffmanTree addNode(Node node){ nodes.add(node); return this; } /** * 快速排序 */ private void quickSort(){ sort(0,nodes.size()-1); } /** * 快速排序的具体实现过程 * @param start * @param end */ private void sort(int start,int end){ if(start<end){ double temp=nodes.get(start).getWeight(); int i=start; int j=end+1; while(true){ while(i<end&&nodes.get(++i).getWeight()<=temp); while(j>start&&nodes.get(--j).getWeight()>=temp); if(i<j){ swap(i,j); }else{ break; } } swap(start,j); sort(start,j-1); sort(j+1,end); } } /** * 结点交换 * @param i * @param j */ private void swap(int i,int j){ Node temp; temp=nodes.get(i); nodes.set(i, nodes.get(j)); nodes.set(j, temp); } /** * 生成哈夫曼树,返回根结点 * @return */ public Node crreateHuffmanTree(){ //当结点集合中只有一个结点(即根结点)时结束 while(nodes.size()>1){ //对当前结合中的结点进行排序(结点集合中的结点个数每次都会改变) quickSort(); //取到两个权值最小的结点 Node left=nodes.get(0); Node right=nodes.get(1); //新结点 Node newNode=new Node(null,left.getWeight()+right.getWeight()); newNode.setLeftNode(left); newNode.setRightNode(right); //移除两个最小的结点 nodes.remove(0); nodes.remove(0); //添加新结点 nodes.add(newNode); } //返回根结点 return nodes.get(0); } //广度优先遍历(需要借助队列) public List<Node> breadthFirst(Node root){ //保存结果集 List<Node> lists=new ArrayList<Node>(); //队列 Queue<Node> queue=new ArrayDeque<Node>(); if(root!=null){ //加入结点到队列中 queue.offer(root); } //如果队列为空,则结束 while(!queue.isEmpty()){ //peek方法不移除结点 lists.add(queue.peek()); //弹出且移除 Node p=queue.poll(); //如果左结点不为空,则加入队列 if(p.getLeftNode()!=null){ queue.offer(p.getLeftNode()); } //如果右结点不为空,则加入队列 if(p.getRightNode()!=null){ queue.offer(p.getRightNode()); } } return lists; } }
package huffman_binary_tree; import java.util.HashMap; import java.util.Map; public class HuffmanCoding { Map<String,String> map=new HashMap<String,String>(); public Map<String,String> coding(Node root){ process(root,""); return map; } private void process(Node node,String content){ //叶子结点 if(node.getLeftNode()==null){ map.put(node.getData(), content); return; } //对左子树分配代码"0" process(node.getLeftNode(),content+"0"); //对右子树分配代码"1" process(node.getRightNode(),content+"1"); } }
package huffman_binary_tree; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; //最优二叉树,哈夫曼树 public class Main { public static void main(String[] args) { HuffmanTree tree=new HuffmanTree(); tree.addNode(new Node("A",40.0)) .addNode(new Node("B",8.0)) .addNode(new Node("C",10.0)) .addNode(new Node("D",30.0)) .addNode(new Node("E",10.0)) .addNode(new Node("F",2.0)); Node root=tree.crreateHuffmanTree(); //广度遍历 // List<Node> lists=tree.breadthFirst(root); // for(Node node:lists){ // System.out.println(node); // } HuffmanCoding coding=new HuffmanCoding(); Map<String,String> map=coding.coding(root); Set<String> mapSet=map.keySet(); //TreeSet实现排序 TreeSet<String> set=new TreeSet<String>(mapSet); Iterator<String> iterator=set.iterator(); while(iterator.hasNext()){ String str=iterator.next(); System.out.println(str+":"+map.get(str)); } } }
A:0 B:1101 C:1110 D:10 E:1111 F:1100