标签:
所谓哈夫曼树就是要求最小加权路径长度,这是什么意思呢?简而言之,就是要所有的节点对应的路径长度(高度-1)乘以该节点的权值,然后保证这些结果之和最小。
哈夫曼树最常用的应用就是解决编码问题。一般我们用的ASCII是固定长度的编码,对于那些常用的字符,使用很长的长度就显得略为浪费空间了。
下面以一个实例来构建一颗哈夫曼编码树。
设字符集S={A,B,C,D,E,F},字符出现的频率W={2,3,5,7,9,12},对字符集进行哈夫曼编码
(1)以频率为树的节点值,构建6个树节点,保存在一个数据集合T中
(2)选择频率集W中最小的两个频率,然后相加,将结果作为树的节点值,构建新的树节点,将这两个最小值对应的树节点,分别作为新的节点的左右孩子。从T重删除这两个最小值对应的节点,最后将新节点放到T中。
(3)重复第2步,直到T中只剩下一个节点,那么该节点就是所需要的哈夫曼树
其实说的容易,实现起来也有一点小麻烦,下面用java实现:
树节点:
public class TreeNode<T> { public TreeNode<T> leftNode; public TreeNode<T> rightNode; public T data; public TreeNode(T data) { this.data=data; } }构建哈夫曼树:
public class TestTree { /* * 设S={A,B,C,D,E,F},W={2,3,5,7,9,12} */ static HashMap<Character, Integer> map; public TestTree() { // TODO Auto-generated constructor stub } public static void main(String[] args) { Character[] character = { 'A', 'B', 'C', 'D', 'E', 'F' }; int[] weight = { 2, 3, 5, 7, 9, 12 };// 有序或者无序都一样 map=new HashMap<Character, Integer>(); for(int i=0;i<weight.length;i++) map.put(character[i], weight[i]); ArrayList<TreeNode<Integer>> nodes = new ArrayList<TreeNode<Integer>>(); for (int i = 0; i < weight.length; i++) { nodes.add(new TreeNode<Integer>(weight[i])); } while (true) { if (nodes.size() <= 1) break; // 找两个最小的 TreeNode<Integer> minNode = nodes.get(0); TreeNode<Integer> sminNode = nodes.get(1); for (int i = 1; i < nodes.size(); i++) { TreeNode<Integer> tempNode = nodes.get(i); if (minNode.data >=tempNode.data) { sminNode = minNode; minNode = tempNode; } } nodes.remove(minNode); nodes.remove(sminNode); TreeNode<Integer> newNode = new TreeNode<Integer>( minNode.data + sminNode.data); newNode.leftNode = minNode; newNode.rightNode = sminNode; nodes.add(newNode); } TreeNode<Integer>hafmanTreeNode=nodes.get(0); getHalmanCode(hafmanTreeNode," "); } public static void getHalmanCode(TreeNode<Integer>hafmanTreeNode,String blank) { if(hafmanTreeNode==null) return; if(hafmanTreeNode.leftNode==null&&hafmanTreeNode.rightNode==null) { System.out.println("->"+getCharacter(hafmanTreeNode.data)); } else { System.out.print("0"); getHalmanCode(hafmanTreeNode.leftNode,blank+" "); System.out.print(blank+"1"); getHalmanCode(hafmanTreeNode.rightNode,blank+" "); } } //得到某一个字符的编码 public static void getHalmanCode(TreeNode<Integer>hafmanTreeNode,Character character) { if(hafmanTreeNode==null) return; if(hafmanTreeNode.leftNode==null&&hafmanTreeNode.rightNode==null) { if (getCharacter(hafmanTreeNode.data)==character) { System.out.print(""); } } } //得到权值对应的字符 public static Character getCharacter(int weight) { Set<Map.Entry<Character, Integer>>set=map.entrySet(); for(Iterator<Map.Entry<Character, Integer>> iterator=set.iterator();iterator.hasNext();) { Map.Entry<Character, Integer>entry=iterator.next(); if(entry.getValue()==weight) { map.remove(entry.getKey()); return entry.getKey(); } } return null; } }结果:
D:00
E:01
A:1000
B:1001
C:101
F:11
标签:
原文地址:http://blog.csdn.net/yilip/article/details/45032801