详细图解哈夫曼Huffman编码树

详细图解哈夫曼Huffman编码树1 引言 霍夫曼 Huffman 编码算法是基于二叉树构建编码压缩结构的 它是数据压缩中经典的一种算法 算法根据文本字符出现的频率 重新对字符进行编码 因为为了缩短编码的长度 我们自然希望频率越高的词 编码越短 这样最终才能最大化压缩存储文本数据的空间 假设现在我们要对下面这句歌词 wewillwewill 进行压缩 我们可以想象 如果是使用 ASCII 码对这句话编码结果

1 引言

  哈夫曼(Huffman)编码算法是基于二叉树构建编码压缩结构的,它是数据压缩中经典的一种算法。算法根据文本字符出现的频率,重新对字符进行编码。因为为了缩短编码的长度,我们自然希望频率越高的词,编码越短,这样最终才能最大化压缩存储文本数据的空间。
  假设现在我们要对下面这句歌词“we will we will r u”进行压缩。我们可以想象,如果是使用ASCII码对这句话编码结果则为:119 101 32 119 105 108 108 32 119 101 32 119 105 108 108 32 114 32 117(十进制表示)。我们可以看出需要19个字节,也就是至少需要152位的内存空间去存储这些数据。
  很显然直接ASCII码编码是很浪费空间的,Unicode就更不用说了,下面我们先来统计一下这句话中每个字符出现的频率。如下表,按频率高低已排序:



这里写图片描述

2 哈夫曼二叉树构建

2.1 初始队列

  那么我们按出现频率高低将其放入一个优先级队列中,从左到右依次为频率逐渐增加。



这里写图片描述



  下面我们需要将这个队列转换成哈夫曼二叉树,哈夫曼二叉树是一颗带权重的二叉树,权重是由队列中每个字符出现的次数所决定的。并且哈夫曼二叉树始终保证权重越大的字符出现在越高的地方。

2.2 第一步合并

  首先我们从左到右进行合并,依次构建二叉树。第一步取前两个字符u和r来构造初始二叉树,第一个字符作为左节点,第二个元素作为右节点,然后两个元素相加作为新空元素,并且两者权重相加作为新元素的权重。



这里写图片描述


  同理,新元素可以和字符i再合并,如下:


这里写图片描述

2.3 重新调整队列

  上图新元素权重相加后结果是变大了,需要对权重进行重新排序。



这里写图片描述


  然后再依次从左到右合并,每合并一次则进行一次队列重新排序调整。如下:


这里写图片描述


  经过多步操作之后,得到以下的哈夫曼二叉树结构,也就是一个带有权重的二叉树:


这里写图片描述

2.4 哈夫曼编码

  有了上面带权重的二叉树之后,我们就可以进行编码了。我们把二叉树分支中左边的支路编码为0,右边分支表示为1,如下图:



这里写图片描述


  这样依次遍历这颗二叉树就可以获取得到所有字符的编码了。例如:‘ ’的编码为10,‘l’的编码为00,‘u’的编码为11100等等。经过这个编码设置之后我们可以发现,出现频率越高的字符越会在上层,这样它的编码越短;出现频率越低的字符越会在下层,编码越短。经过这样的设计,最终整个文本存储空间才会最大化的缩减。
  最终我们可以得到下面这张编码表:



这里写图片描述

2.5 字符串编码

  有了上面的编码表之后,”we will we will r u”这句重新进行编码就可以得到很大的压缩,编码表示为:01 110 10 01 1111 00 00 10 01 110 10 01 1111 00 00 10 11101 10 11100。这样最终我们只需50位内存,比原ASCII码表示节约了2/3空间,效果还是很理想的。当然现实中不是简单这样表示的,还需要考虑很多问题。

3 补充

  我们需要弄明白哈夫曼二叉树概念,它是带权路径达到最小的二叉树,也叫最优二叉树。它不一定是完全二叉树,也不一定是平衡二叉树,它们描述的完全不是一件事情,完全没有概念上的重叠关系。


  个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!
  转载请注明出处:http://blog.csdn.net/fx/article/details/






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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/210255.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午7:58
下一篇 2026年3月19日 上午7:58


相关推荐

  • 使用vue-cli创建项目_vuecli3什么时候出的

    使用vue-cli创建项目_vuecli3什么时候出的vue-cli创建项目上一篇我们安装了vue-cli,接下来我们就使用该脚手架进行创建项目1.进入一个目录,创建项目创建项目命令如下:vuecreate<ProjectName&g

    2022年7月29日
    9
  • 学习 node.js 第八天:Socket 通讯「建议收藏」

    学习 node.js 第八天:Socket 通讯「建议收藏」一般来讲,HTTP是基于文本的“单向”通讯机制。这里所谓的“单向”,乃相对于“双向”而言,因为HTTP服务器只需根据请求返还恰当的HTML给客户端即可,不涉及客户端向服务端的通讯。这种单向的机制比较简单,对网络质量要求也不高。而更多的场景则是需要可靠、稳定的端到端连接。一般这种服务是实时的、有态的而且是长连接,长连接则暗示两段须达致相向通讯的能力,也就说是服务端客户端两者间能够实时地相互间通信。毫无疑问,能够实时通信的服务器正是我们对服务器基本要求之一。区别于HTTP服务器以HTTP为通讯

    2022年6月11日
    54
  • c语言如何生成csv文件格式,生成 csv 文件「建议收藏」

    c语言如何生成csv文件格式,生成 csv 文件「建议收藏」生成CSV文件:有时候我们做的网站,需要将一些数据,生成有一个CSV文件给浏览器,并且是作为附件的形式下载下来。以下将讲解如何生成CSV文件。生成小的CSV文件:这里将用一个生成小的CSV文件为例,来把生成CSV文件的技术要点讲到位。我们用Python内置的csv模块来处理csv文件,并且使用HttpResponse来将csv文件返回回去。示例代码如下:代码解释…

    2022年7月20日
    31
  • labelme怎么安装_putty安装教程

    labelme怎么安装_putty安装教程Labelme安装教程(基于anaconda)1.创建anaconda虚拟环境labelmecondacreate-nlabelmepython=3.6完成之后如图所示(由于我已经创建了labelme故这里用labelme1代替)激活环境:condaactivatelabelme执行完这一步会发现运行环境转移到了labelme,如果没有重新创建2.安装labelme所需要的依赖环境安装的时候使用pip或者conda都可以,两者之中有一个不行时尝试使用另一个,我在安装的时

    2025年10月27日
    4
  • LSTM 时间序列预测 matlab

    由于参加了一个小的课题,是关于时间序列预测的。平时习惯用matlab,网上这种资源就比较少。借鉴了 http://blog.csdn.net/u010540396/article/details/52797489 的内容,稍微修改了一下程序。程序说明:DATA.mat是一行时序值,numdely是用前numdely个点预测当前点,cell_num是隐含层的数目,cos

    2022年4月6日
    155
  • idea2021.7.16激活码(JetBrains全家桶)「建议收藏」

    (idea2021.7.16激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月21日
    56

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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