- 浏览: 342846 次
- 性别:
- 来自: 上海
-
文章分类
最新评论
-
alafqq:
很好的一篇启蒙hashmap的文章;HASHTABLE的93行 ...
使用数组和链表实现hash表存储信息 -
小帅1127:
我擦,我还以为有什么大坑呢,这也写出来。。。
if..else if和if..if的区别 -
fncj:
转下http://www.dodoer.com
hadoop单机版搭建图文详解 -
yueshang520:
Spring注解原理的详细剖析与实现 -
fncj:
转下,谢谢http://www.whohelpme.com/b ...
Spring注解原理的详细剖析与实现
哈弗曼的原理,相信在任何一本数据结构书上都有,就是那么点东西,左0右1叶子串,前缀不能有重复,重者码短轻者长
1、 哈夫曼算法的应用?
主要应用是编码和译码。编码可降低数据的冗余,可节省大约20%的空间(来自网络,说不定是和我一样的菜鸟统计出来的),一般对文件进行压缩与解压缩。 利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
2、哈夫曼编码生成步骤:
①扫描要压缩的文件,对字符出现的频率进行计算。
②把字符按出现的频率进行排序,组成一个队列。
③把出现频率最低(权值)的两个字符作为叶子节点,它们的权值之和为根节点组成一棵树。
④把上面叶子节点的两个字符从队列中移除,并把它们组成的根节点加入到队列。
⑤把队列重新进行排序。重复步骤③④⑤直到队列中只有一个节点为止。
⑥把这棵树上的根节点定义为0(可自行定义0或1)左边为0,右边为1。这样就可以得到每个叶子节点的哈夫曼编码了。
(此总结来自vegbird)
下面是java代码实现
public class HuffmanTree { //①以一段字符串模仿要压缩的文件,扫面,统计出每个字符出现的频率 //返回字符队列 public List<TreeData> countData(String s){ //存放TreeData统计结果的list List<TreeData> datasList=new ArrayList(); for(int i=0;i<s.length();i++){//顺序遍历字符串中的每个字符 char c=s.charAt(i);//获取当前字符 String cs=""+c;//将该字符转换为字符串 boolean isExist=false; for(int t=0;t<datasList.size();t++){//遍历TreeData中的值 TreeData tempData=new TreeData(); tempData=datasList.get(t);//获取当前队列中的值 if(tempData.getS().equals(cs)){//TreeData队列中已经存在cs字符 tempData.setRate(tempData.getRate()+1); isExist=true; break; } } //如果不存在,创建一个TreeData对象,添加到队列中去 if(!isExist){ TreeData newData=new TreeData(); newData.setS(cs); newData.setRate(1); datasList.add(newData); } } return datasList; } //将统计好的TreeData存放到TreeNode中去 //返回TreeNode队列 public List<TreeNode> change_to_TreeNode(List<TreeData> datas){ List<TreeNode> nodeList=new ArrayList(); for(int i=0;i<datas.size();i++){ TreeData data=datas.get(i);//获取datas当前的数据 TreeNode<TreeData> temp=new TreeNode();//新建一个TreeNode temp.setElem(data);//将TreeData加入到新的TreeNode中 nodeList.add(temp);//将新的TreeNode加入到队列中去 } return nodeList; } //②把字符按出现的频率进行排序,放入队列中 //将统计好的TreeNode根据data的rate进行排序 public void sort_Node(List<TreeNode> nodes){ TreeNode<TreeData> temp=new TreeNode(); for(int i=0;i<nodes.size();i++){ TreeNode<TreeData> node_i=nodes.get(i); for(int j=i+1;j<nodes.size();j++){ TreeNode<TreeData> node_j=nodes.get(j); temp.setLeft(node_j.getLeft()); temp.setRight(node_j.getRight()); temp.setElem(node_j.getElem()); //如果rate_i>rate_j if(node_i.getElem().getRate()>node_j.getElem().getRate()){ node_j.setElem(node_i.getElem()); node_j.setLeft(node_i.getLeft()); node_j.setRight(node_i.getRight()); node_i.setElem(temp.getElem()); node_i.setLeft(temp.getLeft()); node_i.setRight(temp.getLeft()); } } } } //根据排序好的TreeNode建立哈弗曼树,返回树根节点 public TreeNode create_Huff(List<TreeNode> nodes){ while(true){ //⑤把队列重新进行排序。重复步骤③④⑤直到队列中只有一个节点为止。 sort_Node(nodes); //创建父节点 TreeNode<TreeData> root=new TreeNode(); //新建两个节点 //③把出现频率最低(权值)的两个字符作为叶子节点,它们的权值之和 //④把上面叶子节点的两个字符从队列中移除,并把它们组成的根节点加入到队列。 TreeNode<TreeData> left=nodes.remove(0);//获取队列中当前首个节点 TreeNode<TreeData> right=nodes.remove(0);//获取队列中当前首个节点 TreeData data=new TreeData(); data.setRate(left.getElem().getRate()+right.getElem().getRate()); data.setS("我是内部节点"); root.setElem(data); //建立关系 root.setLeft(left); root.setRight(right); left.setParent(root); right.setParent(root); if(nodes.size()==0){//如果是最后一个节点 root.getElem().setS("我是根节点!"); return root; } //将父节点放入队列中 nodes.add(0,root); } } //查找指定字符对应的权值与huffman码辅助函数 public String getHTRateHelp(String keyCode,String Hcode,TreeNode Hroot){ String hcode=""; TreeData data=new TreeData(); if(Hroot!=null){//递归结束条件 data=(TreeData) Hroot.getElem();//确保data不为空 if(Hroot.getLeft()==null&&Hroot.getRight()==null){//遍历到了叶节点 data.setHcode(Hcode);//将生成的huffman码赋值给叶节点的Hcode if(keyCode.equals(data.getHcode())){ System.out.println("keyCode:"+keyCode+"--huffmanCode:"+Hcode); hcode=Hcode;//将获取的哈弗曼码赋给hcode } } //递归调用,在查找的同时生成哈弗曼码 //⑥把这棵树上的根节点定义为0(可自行定义0或1)左边为0,右边为1。 //这样就可以得到每个叶子节点的哈夫曼编码了。 getHTRateHelp(keyCode,Hcode+"0",Hroot.getLeft()); getHTRateHelp(keyCode,Hcode+"1",Hroot.getRight()); } return hcode; } //输入指定字符,查找该字符对应的权值与huffman码 public String getHTRate(String keyCode,TreeNode Hroot){ return getHTRateHelp(keyCode,"",Hroot); } //遍历打印出全树 public void printTree(TreeNode Hroot){ TreeData data=new TreeData(); if(Hroot!=null){//递归结束条件 data=(TreeData) Hroot.getElem(); System.out.println("s:"+data.getS()+"--rate:"+data.getRate()); printTree(Hroot.getLeft()); printTree(Hroot.getRight()); } } //遍历打印出H树 public void printHTree(String hcode,TreeNode Hroot){ TreeData data=new TreeData(); if(Hroot!=null){//递归结束条件 data=(TreeData) Hroot.getElem(); if(Hroot.getLeft()==null&Hroot.getRight()==null){ data.setHcode(hcode);//将获取的哈弗曼码赋给data的hcode System.out.println("s:"+data.getS()+"--rate:"+data.getRate() +"--hcode:"+data.getHcode()); } printHTree(hcode+"0",Hroot.getLeft()); printHTree(hcode+"1",Hroot.getRight()); } } /** * @param args */ public static void main(String[] args) { HuffmanTree ht=new HuffmanTree(); String s="iwannllabefyyyyyfffeeeeeefffreeanwannwwwwwatofbrrtttoooolylalalalalalal"; List<TreeData> datas=ht.countData(s); System.out.println("排序前:"); for(int i=0;i<datas.size();i++){ TreeData data=datas.get(i); System.out.println(i+": "+data); } List<TreeNode> nodes=ht.change_to_TreeNode(datas);//将datas的队列转存到nodes队列中去 ht.sort_Node(nodes);//对队列进行排序 System.out.println("排序后:"); for(int i=0;i<nodes.size();i++){ TreeNode node=nodes.get(i); System.out.println(i+": "+node.getElem()); } TreeNode Hroot=ht.create_Huff(nodes); System.out.println("整个树为:"); ht.printTree(Hroot); System.out.println("哈弗曼树叶节点编码为:"); ht.printHTree("", Hroot);//需要传入一个空串!!代表根节点路径 String findcode="s";//查找字符findcode的哈弗曼码 ht.getHTRate(findcode,Hroot); } }
这段代码之前照本宣科的写了一遍,但前几天总结时再写一遍才真正的闻到到一点这段代码所实现的逻辑和功能的味道。
3、解码就是把编码的过程反过来执行一遍。
评论
2 楼
Adminduan
2013-03-26
Adminduan 写道
你好,请问一下文中的treeNode是什么?还望指教
我觉的该类中有 treedate elem ,left,right,但是在排序的时候突然冒出来 left和right这个值是什么那?
1 楼
Adminduan
2013-03-26
你好,请问一下文中的treeNode是什么?还望指教
发表评论
-
apache日志信息详解
2011-11-06 21:19 6319一、访问日志的格式 Apache内建了记录服务器 ... -
浏览器如何工作
2011-08-19 08:57 0http://taligarsiel.com/Projects ... -
编码实现用JDK中的Proxy实现springAOP功能
2011-08-18 15:04 792http://blog.csdn.net/iamtheevil ... -
Spring注解原理的详细剖析与实现
2011-08-14 23:09 84350本文主要分为三部分: ... -
Spring装配基本属性的原理分析与代码实现
2011-08-11 15:37 1481首先,做一个配置属性的基本测试。修改beans.xml,使引用 ... -
编码剖析Spring依赖注入的原理
2011-08-10 20:01 1868一、注入依赖对象 基本类型对象注入: <b ... -
Spring的三种实例化Bean的方法
2011-08-10 14:03 1Spring的三种实例化Bean的方法 1、 使用 ... -
Spring管理bean的原理自定义实现
2011-08-10 10:44 62441、Spring通过BeanDefinition管理基于S ... -
spring环境搭建与测试
2011-08-10 08:40 3473Chapter1、搭建与测试spring的环境 1、 ... -
java回调机制实现
2011-08-08 09:06 2107Java的接口支持提供了一种获得回调的等价功能的 ... -
log4j的使用与详细分析
2011-08-05 13:32 2693一、什么是log4j? http://logging.a ... -
log4j使用详解
2011-08-04 23:05 2http://logging.apache.org/log4j ... -
java解析XML的四种方法的学习与比较
2011-03-30 20:55 7295四种XML解析方法: ... -
自定义日志模块实现
2011-03-30 09:58 1167package wxy.XXXX.Utils; impo ... -
synchronized(this)
2011-03-29 09:17 70581、当两个并发线程访问同一个对象object中的这个synch ... -
详细解析Java中抽象类和接口的区别(转)
2011-03-24 23:48 976在Java语言中, abstract cl ... -
NIO学习笔记(三)---通道
2011-03-09 23:06 16051、通道基础 ... -
NIO学习笔记(2)--缓冲区
2011-03-09 18:20 9901、一个Buffer对象是固定数量的数据的容器。其作用是 ... -
封锁管理子系统模拟实现java版
2011-03-09 18:01 1247封锁管理子系统模拟实现 文件锁定 ... -
NIO学习笔记(一)I/O缓冲区操作
2011-03-07 20:04 1287上图简单描述了数据从外部磁盘向运行中的进程的内存区域移动的 ...
相关推荐
Java常用代码-java哈弗曼编码的实现.doc
你可以通过阅读源代码来了解自适应哈弗曼编码的实现细节,并尝试修改或优化代码,例如,提高编码速度,或者增加错误检测和恢复功能。 总之,这个压缩包提供了一个完整的自适应哈弗曼编码解决方案,包含理论知识、源...
1. 代码实现:这可能包括了用某种编程语言(如C++、Java或Python)编写的哈弗曼树构建、编码和解码的程序。 2. 运行截图:这些截图可能会展示代码的运行结果,比如输入数据、构建的哈弗曼树图形化表示、编码后的二...
哈弗曼编码是一种高效的数据压缩方法,通过构建哈弗曼树来实现。在这个项目中,学生需要实现哈弗曼树的建立,以及基于哈弗曼编码的文件压缩和解压缩功能。以下是关于这个主题的详细知识讲解: 1. **哈弗曼树...
下面我们将深入探讨哈弗曼编码的原理、实现过程以及如何在Java中编写源代码。 哈弗曼编码的原理: 哈弗曼编码是建立在频率统计基础上的,它将出现频率高的字符赋予较短的编码,频率低的字符则赋予较长的编码。这种...
生成哈弗曼编码则是从根节点出发,向左走记为0,向右走记为1,到达叶节点时,形成的路径就代表了该叶节点的哈弗曼编码。哈弗曼编码具有自定界性,即任意一个编码片段都无法构成另一个编码的前缀,这保证了解码的唯一...
在Java编程语言中,我们可以用面向对象的方式来实现哈弗曼编码。 哈弗曼编码的基本步骤包括: 1. **构建哈弗曼树**: - 首先,收集待编码数据的频率,创建一个包含所有字符及其频率的优先队列(或最小堆)。 - ...
在这个项目中,哈弗曼编码的Java代码被转换成了一个独立的.exe文件,便于用户在Windows系统上直接使用。 通过上述步骤,我们可以看到,这个Java实现的哈弗曼编码项目不仅提供了压缩和解压缩的功能,还考虑到了用户...
在压缩包内的“www.pudn.com.txt”可能是实验数据或者说明文档,而“hafuman”很可能是实现哈弗曼编码和解码的代码文件,可能包含C、C++、Java或Python等编程语言的实现。代码可能包括以下几个关键部分: - **构建...
在提供的压缩包文件"哈弗曼编码"中,可能包含了实现哈弗曼编码的源代码,这些源代码可能用C、C++、Java等编程语言编写,通过链表结构来动态构建和操作哈弗曼树,进而完成编码和解码的过程。通过阅读和理解这些源代码...
总的来说,这个"哈弗曼编码译码系统"涵盖了数据压缩的基础理论,以及在Java编程环境下的具体实现,对于学习数据结构、算法和软件开发都是很好的实践案例。通过此系统,我们可以直观地了解哈弗曼编码的工作原理,并能...
总的来说,这个Java程序实现了对中文文本的哈弗曼编码和解码功能,提供了一种有效的文本压缩解决方案,尤其适合数据量较大的情况,有助于减少存储空间和提高传输效率。通过学习和理解哈弗曼编码的原理以及这个程序的...
这个压缩文件包含了实现哈弗曼编码译码的完整代码,适用于数据结构课程设计。学生可以从中学习到如何运用链表、树等数据结构以及算法来实现这一过程。同时,此项目还可以帮助学生理解数据压缩的基本原理和实际应用,...
2. **算法实现**:实验报告可能包含了用某种编程语言(如C++、Python或Java)实现的哈弗曼编码算法。代码可能会包括两个主要功能:一是构建哈弗曼树,二是根据树生成编码。构建过程通常涉及一个优先队列来处理节点的...
在Java中实现哈弗曼编码译码器,通常会涉及以下几个关键步骤: 1. **频率统计**:首先,需要读取待压缩文件,并统计每个字节或字符出现的频率。这是构建哈弗曼树的基础。对于大文件(如2G以下),可以采用分块处理...
4. **Test.java**:这是测试代码,用于验证哈弗曼编码的正确性。它可能包含一些单元测试,比如创建一个已知频率的字符集,构建哈弗曼树,生成编码,然后解码回原始数据,确保压缩和解压过程是可逆的。 在Java实现...
设计一个可视化窗体,实现文本内容与其编码信息的互译,基本要求为:一个区域中输入文本信息,按照哈夫曼编码机制,在另一个区域中输出相应的哈夫曼编码信息,同时在第三个区域中显示对编码信息的反编译结果。...
通过阅读和理解`Ha.java`的代码,你可以更深入地学习如何在Java中实现哈弗曼编码,包括如何处理数据结构、算法逻辑以及文件操作等重要知识点。这对于提升Java编程技能,尤其是数据压缩和算法实现能力具有很大帮助。
它通过对文件中的字符频率进行统计,然后构建出一个哈弗曼树,进而得到每个字符的哈弗曼编码(一种变长编码),从而实现对原始数据的有效压缩。 ### 3. 代码结构解析 #### 3.1 数据结构定义 - `hnodetype` 结构体...