JavaDemo——哈夫曼树

哈夫曼树构造过程:

列表里选出权重(或者出现次数)最低的两个,构成新树的左右子节点,新树父节点的权重为这两个子节点权重之和,将父节点(树)丢进列表里,重复操作,最后列表只剩一个,即哈夫曼树,所有子树的左边标0右边标1,节点的路径即哈夫曼编码;

Demo:

package testHuffman;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class TestHuffman {

	public static void main(String[] args) {
		//优先级队列,自动排序
		PriorityQueue<Node> q = new PriorityQueue<>(new Comparator<Node>() {
			@Override
			public int compare(Node o1, Node o2) {
				if(o1.priority == o2.priority) {
					return o1.n-o2.n;
				}else {
					return o1.priority - o2.priority;
				}
			}
		});
		//初始数据
		Map<String,Integer> map = new HashMap<>();
		map.put("A",5);
		map.put("B",24);
		map.put("C",7);
		map.put("D",17);
		map.put("E",34);
		map.put("F",5);
		map.put("G",13);
		//初始数据放入队列
		for(String v:map.keySet()) {
			System.out.println("放入队列:"+v+":"+map.get(v));
			q.add(new Node(map.get(v), v, null, null, 1));
		}
		System.out.println("=队列="+q);
		//构造哈夫曼树
		while(q.size()>1) {
			//取出优先级最小的两个
			Node n1 = q.poll();
			Node n2 = q.poll();
			System.out.println("取出:"+n1+n2);
			//构成新树
			Node newNode = new Node(n1.priority+n2.priority, "("+n1.name+""+n2.name+")", n1, n2, n1.n>n2.n?n1.n+1:n2.n+1);
			System.out.println("放入:"+newNode);
			//重新放入队列
			q.add(newNode);
			System.out.println("=队列="+q);
		}
		//取出哈夫曼树
		Node tree = q.poll();
		Map<String, String> code_word = getTreeCode(tree);
		System.out.println(code_word);
		
		Map<String, String> word_code = new HashMap<>();
		for(String code:code_word.keySet()) {
			word_code.put(code_word.get(code), code);
		}
		
		//测试
		String msg = "DCABCFDBFABEGA";
		for(String word:word_code.keySet()) {
			msg = msg.replaceAll(word, word_code.get(word));
		}
		System.out.println("编码:"+msg);
		
		String subCode = "";
		String reMsg = "";
		for(int i=0;i<msg.length();i++) {
			subCode += msg.substring(i, i+1);
			if(code_word.containsKey(subCode)) {
				reMsg += code_word.get(subCode);
				subCode = "";
			}
		}
		System.out.println("消息:"+reMsg);
	}
	
	private static Map<String,String> getTreeCode(Node root) {
		Map<String,String> m = new HashMap<>();
		getRoad("",root,m);
		return m;
	}
	//构造路径,左0右1
	private static Map<String,String> getRoad(String r, Node n, Map<String,String> m) {
		if(n.left == null) {
			m.put(r, n.name);
		}else {
			getRoad(r+"0", n.left, m);
		}
		if(n.right == null) {
			m.put(r, n.name);
		}else {
			getRoad(r+"1", n.right, m);
		}
		return m;
	}
}
class Node{
	public int priority;
	public String name;
	public Node left;
	public Node right;
	public int n;//用于保存树层级,优先级相同按层级排序,每次选层级最小的两个

	public Node(int priority, String name, Node left, Node right, int n) {
		this.priority = priority;
		this.name = name;
		this.left = left;
		this.right = right;
		this.n = n;
	}

	@Override
	public String toString() {
		return "{"+priority + ":" + name+"}";
	}
}

结果:

同组数据产生的哈夫曼树可能不唯一,存在超过两个相同权重节点的选择问题和左右子树的位置问题;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值