哈夫曼编码(java版)

来源:互联网 发布:淘宝怎么加入淘客 编辑:程序博客网 时间:2024/05/29 09:36

哈夫曼树又叫最优二叉树,是一类带权路径最短的二叉树。哈夫曼树是二叉树的一种应用,在信息检索中很常用。

哈夫曼树可以用来解决报文编码问题,在通信领域有着非常广泛的运用。具体什么是带权路径二叉树,什么是哈夫曼编码这里不做介绍,这里只介绍代码,必须先知道这些概念才能阅读代码!

以下为全部代码,做了比较详细的注释,所以不做另外解释

节点类:

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;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "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:0B:1101C:1110D:10E:1111F:1100