树论之哈夫曼树

树论之哈夫曼树

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

哈夫曼树构建

  • 哈夫曼树的节点都是叶子节点
  • 根据哈夫曼树的特点,构建树最好的选择当然是从底层开始。
  • 从底层开始构建时应该选择权重最小的2个值开始构建

哈夫曼树的用途

  • 哈夫曼编码是最优前缀码 因此可用于加密解密
  • 文件压缩解压

代码再现

public class HuffmanTree {

	List<TreeNode> leafs;
	
	Map<Character,Integer> weights;
	
	TreeNode rootNode;
	
	Map<Character,String> codeMap;
	Map<String,Character> decodeMap;
	
	private HuffmanTree(Map<Character,Integer> weights) {
		this.weights = weights;
		leafs = new ArrayList<>();
		codeMap = new HashMap<>();
		decodeMap = new HashMap<>();
		initTree();
	}
	
	public void initTree(){
		PriorityQueue<TreeNode> queue = new PriorityQueue();
		Character[] keys =weights.keySet().toArray(new Character[0]);
		weights.keySet().toArray(keys);
		for(Character chr:keys){
			TreeNode treeNode = new TreeNode(chr.toString(),weights.get(chr).intValue());
			queue.add(treeNode);
			leafs.add(treeNode);
		}
		
		for(int n=1;n <= keys.length-1;n++) {
			TreeNode left = queue.poll();
			TreeNode right = queue.poll();
			
			TreeNode newNode = new TreeNode(left.chars+right.chars,left.freq+right.freq);
			newNode.left = left ; 
			newNode.right = right;
			left.parent = newNode;
			right.parent = newNode;
			queue.add(newNode);
		}
		rootNode = queue.poll();
	}
	
	public String encode(String str) {
		StringBuilder sbr = new StringBuilder();
		for(Character c : str.toCharArray()) {
			sbr.append(codeMap.get(c));
		}
		System.out.println(str+"=="+sbr.toString());
		return sbr.toString();
	}
	public void decode(String str) {
		StringBuilder sbr = new StringBuilder();
		StringBuilder temp = new StringBuilder();
		for(Character c : str.toCharArray()) {
			temp.append(c);
			if(decodeMap.containsKey(temp.toString())) {
				sbr.append(decodeMap.get(temp.toString()));
				temp = new StringBuilder();
			}
		}
		System.out.println(str+"=="+sbr.toString());
	}
	
	public void codes(){
		for(int i=0;i<leafs.size();i++) {
			TreeNode current = leafs.get(i);
			Character c = current.chars.charAt(0);
			String codes = "";
		     while(current.parent!=null) {
		    	 if(current == current.parent.left) {
		    		 codes="0"+codes;
		    	 }else {
		    		 codes="1"+codes;
		    	 }
		    	 current = current.parent;
		     }
		     System.out.println(c+"::"+codes);
		     codeMap.put(c, codes);
		     decodeMap.put(codes, c);
		}
	}
	
	public static void main(String[] args) {
		Map<Character,Integer> weights =new HashMap<Character,Integer>();
		weights.put('a', 3);
		weights.put('b', 24);
		weights.put('c', 6);
		weights.put('d', 20);
		weights.put('e', 34);
		weights.put('f', 4);
		weights.put('g', 12);
		HuffmanTree huffman = new HuffmanTree(weights);
		huffman.codes();
		huffman.decode(huffman.encode("afeddacbad"));
	}
	
	static class TreeNode implements Comparable<TreeNode>{
		private String chars;//节点字符
		private int freq;//权重
		private TreeNode left;//左节点
		private TreeNode right;//右节点
		private TreeNode parent;//父节点
		
		private TreeNode(String chars,int freq) {
			this.chars = chars;
			this.freq = freq;
		}

		@Override
		public int compareTo(TreeNode o) {
			return this.freq-o.freq;
		}
	}
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值