您的位置:首页 > 其它

哈夫曼树--链式结构(建立huffman树、编码、解码)

2015-09-15 13:46 645 查看
引子: 用链式结构来建立哈夫曼树。总体思路是: 将每一棵树(这是每一棵树只有一个节点,头节点)放在一个优先队列中(下面的是链表实现的优先队列),频率(rate)小的在队列头,取出队列头两个,频率相加之后组合成一个有三个节点的树,重新放入优先队列中。重复上面的过程,直到最后只剩下一个,则这最后一个便是哈夫曼树。编码:从叶子节点开始往上。解码:从根节点开始往下。
package tree;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;

/**
 * 哈夫曼编码解码
 * @author LiangYH
 *
 */
public class HuffmanTest {

	public static void main(String[] args) {
		HuffmanTest tree1 = new HuffmanTest();
		tree1.setRoot("A", 9);
		
		HuffmanTest tree2 = new HuffmanTest();
		tree2.setRoot("B", 5);
		
		HuffmanTest tree3 = new HuffmanTest();
		tree3.setRoot("C", 8);
		HuffmanTest tree4 = new HuffmanTest();
		tree4.setRoot("E", 19);
		HuffmanTest tree7 = new HuffmanTest();
		tree7.setRoot("F", 11);
		
		
		MyLink link = new MyLink();
		link.add(tree1);
		link.add(tree2);
		link.add(tree3);
		link.add(tree7);
		link.add(tree4);
		link.printLink();
		
		HuffmanTest t1 = null;
		HuffmanTest t2 = null;
		while(link.size() > 1){
			t1 = link.delete();
			t2 = link.delete();
			t2.growTree(t1);
			link.add(t2);
		}
		
		t2.printTree();
		
		Map<String,List<String>> map = t2.getCodeTable();
		
		t2.printCodeTable(map);
		
		List<String> list = t2.encode("AEBCF");
		
		List<String> li2 = t2.decode(list);
		
		System.out.println();
		System.out.print("解码: ");
		for(String s: li2){
			System.out.print(s);
		}
	}
	
	private List<Node> leaves = null;
	private Map<String, List<String>> codeMap= null;
	
	private Node root = null;
	
	
	public HuffmanTest(){
		leaves = new ArrayList<Node>();
		codeMap = new HashMap<String, List<String>>();
	}
	
	public Map<String,List<String>> getCodeMap(){
		return this.codeMap;
	}
	
	public List<Node> getLeaves(){
		getLeaves(root);
		return this.leaves;
	}
	
	public void setRoot(String item, int rate){
		this.root = new Node(item, rate);
	}
	
	public Node getRoot(){
		return this.root;
	}
	
	public int getRateOfRoot(){
		return this.root.rate;
	}
	
	public void growTree(HuffmanTest newTree){
		Node newNode = new Node();
		//设置子节点
		newNode.leftChild = this.root;
		newNode.rightChild = newTree.getRoot();
		//设置父节点
		this.root.parent = newNode;
		newTree.getRoot().parent = newNode;
		//设置父节点的权重
		newNode.setRate(this.root.rate+newTree.getRateOfRoot());
		//重置根节点
		this.root = newNode;
	}
	
	public void InOrderTraverse(HuffmanTest tree){
		traverse(tree.root);
		
	}
	
	private void traverse(Node node){
		if(node != null){
			System.out.print(node.item+"/"+node.rate+"; ");
			traverse(node.leftChild);
			traverse(node.rightChild);
		}
	}
	
	//获取叶子节点
	private void getLeaves(Node node){
		if(node != null){
			if(node.item != null){
				leaves.add(node);
			}
			getLeaves(node.leftChild);
			
			getLeaves(node.rightChild);
		}
	}

	public Map<String,List<String>> getCodeTable(){
		//获取叶子节点
		getLeaves(root);
		int len = leaves.size();
		for(int i = 0; i < len; i++){
			Node tempNode = leaves.get(i);
			List<String> tempList = new ArrayList<String>();
			
			codeMap.put(tempNode.item, tempList);
			
			while(tempNode.parent != null){
				if(tempNode == tempNode.parent.leftChild){
					tempList.add("0");
				}else if(tempNode == tempNode.parent.rightChild){
					tempList.add("1");
				}
				tempNode = tempNode.parent;
			}
		}
		
		return this.codeMap;
	}
	
	public List<String> encode(String target){
		System.out.println();
		System.out.print(target+" 的编码: ");
		
		List<String> li = new ArrayList<String>();
		
		int len = target.length();
		for(int i = 0; i < len; i++){
			String temp = String.valueOf(target.charAt(i));
			List<String> list = codeMap.get(temp);
			for(int k = list.size()-1; k >= 0; k--){
				System.out.print(list.get(k));
				li.add(list.get(k));
			}
		}
		return li;
	}
	
	/**
	 * 解码
	 * @param codeList 二进制编码
	 * @return 解码结果
	 */
	public List<String> decode(List<String> codeList){
		
		List<String> list = new ArrayList<String>();
		
		Node tempNode = null;
		tempNode = root;
		for(String s: codeList){
			if("0".equals(s)){
				tempNode = tempNode.leftChild;
				if(tempNode.item != null){
					list.add(tempNode.item);
					tempNode = root;
					continue;
				}
			}else if("1".equals(s)){
				tempNode = tempNode.rightChild;
				if(tempNode.item != null){
					list.add(tempNode.item);
					tempNode = root;
					continue;
				}
			}
		}
		return list;
	}
	
	public void printTree(){
		InOrderTraverse(this);
	}
	
	public void printCodeTable(Map<String,List<String>> codeTable){
		Set<Entry<String,List<String>>> set = codeTable.entrySet();
		Iterator<Entry<String,List<String>>> iter = set.iterator();
		System.out.println();
		while(iter.hasNext()){
			Entry<String,List<String>> entry = iter.next();
			System.out.print(entry.getKey()+": ");
			
			List<String> li = entry.getValue();
			for(int i = li.size()-1; i >= 0; i--){
				System.out.print(li.get(i));
				
			}
			System.out.print("; ");
		}
	}
	
	class Node{
		Node leftChild = null;
		Node rightChild = null;
		Node parent = null;
		//字母
		String item = null;
		//字母出现的频率
		int rate = 0;
		
		public Node(){
			
		}
		public Node(String item, int rate){
			this.item = item;
			this.rate = rate;
		}
		
		public void setItem(String item){
			this.item = item;
		}
		
		public void setRate(int rate){
			this.rate = rate;
		}
		
		public void printNode(){
			System.out.println(item+"\\"+rate+"; ");
		}
	}
}

/**
 * 优先链表
 * @author LiangYH
 *
 */
class MyLink{
	
	private LinkNode first = null;
	private int size = 0;
	
	
	public MyLink(){
		
	}
	
	/**
	 * 增加节点,并按照相关顺序从小到大排列
	 * @param tree
	 */
	public void add(HuffmanTest tree){
		LinkNode newNode = new LinkNode(tree);
		
		
		if(first == null){
			first = newNode;
			size++;
		}else{
			boolean isNextNull = false;
			LinkNode previous = first;
			LinkNode temp = first;
			while(tree.getRateOfRoot() > temp.tree.getRateOfRoot()){
				if(temp.next == null){
					isNextNull = true;
					break;
				}
				previous = temp;
				temp = temp.next;
			}
			
			//temp所指的是最后一个
			if(isNextNull){
				temp.next = newNode;
				size++;
				return;
			}
			//如果temp指向的是第一个
			if(temp == first){
				newNode.next = first;
				first = newNode;
				size++;
			}else{
				newNode.next = temp;
				previous.next = newNode;
				size++;
			}
			
		}
	}
	
	/**
	 * 删除最左边的一个元素
	 * @return
	 */
	public HuffmanTest delete(){
		if(isEmpty())
			return null;
		
		LinkNode temp = first;
		first = first.next;
		
		size--;
		return temp.tree;
	}
	
	public boolean isEmpty(){
		return first == null;
	}
	
	public int size(){
		return this.size;
	}
	
	public void printLink(){
		LinkNode temp = first;
		while(temp.next != null){
			System.out.print(temp.tree.getRoot().item+"\\"+temp.tree.getRateOfRoot()+"; ");
			temp = temp.next;
		}
		System.out.println(temp.tree.getRoot().item+"\\"+temp.tree.getRateOfRoot());
	}
	
	/**
	 * 内部类
	 * @author LiangYH
	 *
	 */
	class LinkNode{
		LinkNode next = null;
		HuffmanTest tree;
		
		public LinkNode(HuffmanTest tree){
			this.tree = tree;
		}
	}
	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: