贪婪算法-霍夫曼树 霍夫曼编码
2016-04-15 18:08
225 查看
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL= (W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。
哈夫曼编码步骤:
一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止
Java程序如下:
1.构造对象:树的节点
1.对树的集合进行初始化。将给定的字符串进行权重计算(出现的次数),每个字符看做是一个单节点的子树。
测试字符串:
![](http://img.blog.csdn.net/20160415180227226?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
3. 构造霍夫曼树。选择森林中权重最小的两棵树合并成一棵树,将新生成的树加入森林,并且将两棵树删除,循环直至最后合并成一棵树。
构造霍夫曼树的过程测试如下:
![](http://img.blog.csdn.net/20160415180619227?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
4. 对霍夫曼树进行编码并打印
编码结果如下:
哈夫曼编码步骤:
一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止
Java程序如下:
1.构造对象:树的节点
/** * Huffman 树的节点对象 * @author Qing * */ public class HuffmanPoint { private int weight;//权重 private HuffmanPoint lchild, rchild;//父节点 private char value;//leaf 的char值 private String code = "";//Huffman编码 public String getCode() { return code; } public void setCode(String code) { this.code = code; } public HuffmanPoint(char value, int weight){ // TODO Auto-generated constructor stub this.weight = weight; this.value = value; } public void setWeight(int weight){ this.weight = weight; } public int getWeight(){ return this.weight; } public HuffmanPoint getLchild() { return lchild; } public void setLchild(HuffmanPoint lchild) { this.lchild = lchild; } public HuffmanPoint getRchild() { return rchild; } public void setRchild(HuffmanPoint rchild) { this.rchild = rchild; } public char getValue() { return value; } public void setValue(char value) { this.value = value; } }
1.对树的集合进行初始化。将给定的字符串进行权重计算(出现的次数),每个字符看做是一个单节点的子树。
测试字符串:
public static final char text[] = {'q','i','n','g','b','e','a','u','t','y','c','u','t','e','t','r','u','e'};
//初始化,计算每个叶子的权重,并且每个叶子作为一个单独的树 public static void init(){ int length = text.length; int i = 0; while(i < length){ int leaf_i = 0; int flag = 0; while(leaf_i < leafs.size()){ if(leafs.get(leaf_i).getValue() == text[i]){ leafs.get(leaf_i).setWeight(leafs.get(leaf_i).getWeight() + 1);//当有相同的value就将weight +1 flag = 1; break; } leaf_i ++; } if(flag == 0){ HuffmanPoint newleaf = new HuffmanPoint(text[i],1); leafs.add(newleaf); } i++; } trees = leafs; for(int j = 0; j < trees.size(); j ++){ System.out.println(trees.get(j).getValue() + " " + trees.get(j).getWeight()); } }初始化之后的结果:
3. 构造霍夫曼树。选择森林中权重最小的两棵树合并成一棵树,将新生成的树加入森林,并且将两棵树删除,循环直至最后合并成一棵树。
//寻找森林中节点权重最小的树 public static HuffmanPoint find_min(){ int i = 1; HuffmanPoint temp = trees.get(0); while(i < trees.size()){ if(trees.get(i).getWeight() < temp.getWeight()){ temp = trees.get(i); } i ++; } trees.remove(temp); return temp; } //构造霍夫曼树 public static void buildTree(){ HuffmanPoint lchild; HuffmanPoint rchild; while(trees.size() != 1){ HuffmanPoint tree_new = new HuffmanPoint('0',0);//所有不是叶子节点的value值设为0 lchild = find_min(); rchild = find_min(); System.out.println("left " + lchild.getValue() +", right "+ rchild.getValue()); tree_new.setLchild(lchild); tree_new.setRchild(rchild); tree_new.setWeight(lchild.getWeight() + rchild.getWeight()); //从森林中移除两个子树,添加合并后的树 trees.add(tree_new); for(int j = 0; j < trees.size(); j ++){ System.out.print(trees.get(j).getValue() + " " + trees.get(j).getWeight() +"\t"); } System.out.println(" "); } }
构造霍夫曼树的过程测试如下:
4. 对霍夫曼树进行编码并打印
//对树进行编码打印树,利用队列 public static void printTree(){ HuffmanPoint root = trees.get(0); queue.add(root); while(!queue.isEmpty()){ HuffmanPoint point = queue.get(0); System.out.println(point.getValue() + " "+ point.getCode()); //将节点的左子树和右子树放入队列,并将打印出的节点从队列中取走 if(point.getLchild() != null){ HuffmanPoint lchild = point.getLchild(); HuffmanPoint rchild = point.getRchild(); lchild.setCode(point.getCode() + "0"); rchild.setCode(point.getCode() +"1"); queue.add(lchild); queue.add(rchild); } queue.remove(point); } }
编码结果如下:
相关文章推荐
- 又论Node.js的HTTP模块之深入理解
- Java日期差计算天数
- 积累是一种最简单的学习方法
- 对springMVC的简单理解
- HTML5 <template>
- Hibernate一对一单向关联,Hibernate一对一多向关联
- java的输入输出及相关快捷键
- mysql时间格式化
- php实现文件下载控制示例
- 1013. Battle Over Cities
- Java之从键盘输入值赋给变量
- python的数据可视化 graphviz pydot安装配置(win10)
- Http请求get、post工具类
- Python __str__(self)和__unicode__(self)
- Android WifiDisplay分析
- 消除unreferenced local variable警告
- 再来一发邮箱真实性验证
- WPS 数据恢复的好处
- Http请求get、post工具类
- TCP/IP 协议相关