哈夫曼编码(java版)

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

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

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

节点类:

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


  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值