哈夫曼树--链式结构(建立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; } } }
相关文章推荐
- Jquery动态操作checkbox
- oracle exp 命令导大数据
- 任意2n个整数,从其中选出n个整数,使得选出的n个整数和同剩下的n个整数之和的差最小
- ios开发系列之NSDate,NSDateFormatter,NSDateComponents和NSCalendar
- 压缩文件(zip)--适用于目录下既有目录又有文件的情况
- stripes framework(框架)入门教程(附案例分析)
- spring整合mybatis(入门级简单教程5)--使用mybatis的API
- spring整合mybatis(入门级简单教程4)--扫描mapper类
- spring整合mybatis(入门级简单教程3)--获取sqlSession对象
- spring整合mybatis(入门级简单教程2)
- spring整合mybatis(入门级简单教程1)--在spring中配置c3p0,并成功测试
- IDEA加密文件Base64转换String传输以及报文摘要MD5防止恶意篡改
- 使用struts2框架来实现CRUD(create、read、update、delete)
- MVC、JSP实现mysql的增删改查功能的封装和简陋的界面交互
- java坦克游戏
- 贪吃蛇游戏(java)
- 考研成绩查询系统(jsp、mysql、java)
- 用java实现优先级别队列
- 用Java实现单向链表
- iOS各大牛博客