霍夫曼树为何物

霍夫曼树为何物

引子:荒废的空间

    自从盘古开天辟地、仓颉创造文字以来,美帝国的程序猿们在长期实践中就发现了这么一个问题:那些组成文字的26个字母在实际应用中的频率是有差别的。

霍夫曼树为何物

    这就意味着有的字母用到的多,而有的用到的会少一点。so,他们认为凡是字母都用7个比特存储这对于那些常用的字母来说并不公平,实际上造成了大量存储空间的荒废。那么怎样让那些最常用的字母在存储过程中占用较少的字节、又较能方便查找呢?


  • 霍夫曼树简介

        于是,以霍夫曼为代表的机智的程序猿和算分师(算法分析师)们经过一番折腾和探索,为解决这个问题,联想到了堆的应用。因为最大堆(maxium heap)中越大的数字距离根节点越近。因此,如果改进最大堆,使得出现频率越高的字母距离根节点越近,那么搜索出现频率较高的字母的路径不是就变短了吗?他们提出如下图示的解决方案:

霍夫曼树为何物

    根据此图,寻找任何一个树中的元素,都是从根节点开始,0表示向左子树搜索,1表示向右子树搜索,至含有该元素的叶子节点结束,或者返回找不到。比如在一段给定文本中寻找使用频率为120次的字母E,从根节点306开始,搜索左子树即得E,可记为0。再如,搜索使用频率仅为7次的字母K,搜索过程可记为111101.这样,我们就发现查找高频字母的速度比查找低频字母快了很多。同时,我们发现如果就用一个数字0代表E,比用E的Ascii码代表E明显省了6比特。即使是位于树的深处的字母Z和K,我们也仅仅用了6个位。(然而字母多了以后随着层数的增加这种优势可能丧失)这就为节省这段文本的空间找到了一种可能。在当时不少计算机还是通过插卡才能运行的情况下,这样对于部分字母既省时又省空间的解决方案的发现还是能称得上是一件破天荒的事情的。

  • 论霍夫曼树的栽培方法

    俗话说“前人栽树后人乘凉”。那么这么好的一棵树是怎么栽起来以备日后使用的呢?我们还是以简介中那棵树的构造过程为例。首先,对出现的字母以频率为关键字进行堆排序(此时先选择最小堆),会得到一个数组如下:

霍夫曼树为何物

把这个堆最小的两个元素推出,作为霍夫曼树的叶子节点,它们的和作为暂时的根并推入刚才的最小堆,得到以下结果:

霍夫曼树为何物接下来的事情依次类推,推出两个元素9和24:M,在已有树的基础上构造新树,推入它们的和33,形成以下结果:

霍夫曼树为何物

有时会出现一种特殊情况,由于上一步推入堆的和太大,连续推出的两个或多个元素都是带有数字和字母的节点,如下图所示,后两个推出的元素是37:U以及42:L:

霍夫曼树为何物

 

那么此时,我们就先把推出的两个节点形成另一颗树,根即为它们的和79,再将79推入堆。后面的事情则继续照常进行。因此,每次这样推出2个元素,推入一个元素,这个堆就总有身子被掏空的时候,那个时候只要把这个堆交给各大编程语言的垃圾回收机制,霍夫曼树就算种好了。本例的结果参见简介部分那棵树即可。

  • 后记:由霍夫曼树想到什么

     我们的中文字符比英语那26个字母复杂得多,这就意味着对于中文字符查找、存储的需求就会更多样化。那么霍夫曼树能否用于中文字符的压缩、存储和查找呢?其二,文本统计得越多,关于字符出现频率的规律就掌握得越准确。那么,是否可以设计一种方法让程序自动统计文本中字符的个数、自动去维护已经种好的树呢?其三,文本可以这么搞,那么数字呢?音频呢?MV呢?甚至计算机病毒的特征存储与分析呢?……笔者认为,这种树引进中国,在对于我国日常工作中用到的数据用它进行处理,可能会带来软件行业的枝繁叶茂,体现在存储和查找的效率可能会被大大提高。因此学习栽种霍夫曼树这个品种的树前景还是比较看好的。上述具体过程,参见笔者分享的代码:简版霍夫曼树,链接:

http://www.oschina.net/code/snippet_2626980_58384

 

参考资料:

《数据结构与算法分析(C++版)》第三版

转载于:https://my.oschina.net/Samyan/blog/726772

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108923.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 个人对json的一些简单理解「建议收藏」

    个人对json的一些简单理解「建议收藏」在最近的学习中,查阅了很多资料,了解了一些关于json的基本知识,下面做一个简单的总结:json是什么没有.json结尾的这种文件,json(JavaScriptObjectNotation)是一种简单的数据交换格式,在此之前我也不知道这个东西其实没有想象的那么抽象,看看后面的例子会更清晰json中的数据结构json中只有两种数据基本结构,一种是MAP,或者叫对象,另一种是Ar…

  • 数据库置疑修复_sqlserver错误日志在哪里

    数据库置疑修复_sqlserver错误日志在哪里这篇文章在我电脑上呆得太久了,也不知道还有没有用

  • getdate()方法_formatdatetime函数

    getdate()方法_formatdatetime函数今天看博客看到了一个关于字符串处理的方法,突然就想到可以用来格式化数据,相比之前我是用判断然后用字符串拼接的方法,比较繁琐,感觉这样做会更加好些。1.str0.padStart(length,str1),将指定字符串str1按照长度填充到字符串str0的头部2.关于月份month和日day为个位数的处理如下:varnowTime=newDate()varnowMonth=String(nowTime.getMonth()+1).padStart(2,’0′)…

  • linux系统如何修改用户名_两种方案对比报告

    linux系统如何修改用户名_两种方案对比报告在安装系统的时候,经常会无意识的随便起个用户名,后面如果发现该用户名不好或因为环境需要须重起个用户名,经过查找资料和亲自测试发现有两种方案可选:手动修改和使用usermod等命令自动修改。方案一:手动修改各个关联用户文件以root身份登录系统文件的修改需要root权限,这里不管是原root用户登录还是普通用户切换到root下都可以,只要有修改权限就行。修改/etc/passwd这个文件中的用户名部

  • 【007】【JVM——内存分配和恢复策略】

    【007】【JVM——内存分配和恢复策略】

  • android之activity的生命周期详解

    刚在看mars老师的视频,看到activity的生命周期,感觉挺有收获,就总结了一下.为了更清楚的看清楚工作的具体过程,举例如下:,建立两个activity,一个main,一个another,在main里面放置button加监听器跳转向another,在每个复写的activity的状态方法里都加一个log输出,比如onCrea

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号