7分钟0基础彻底理解常用数据压缩原理---哈夫曼编码

本文主要是介绍7分钟0基础彻底理解常用数据压缩原理---哈夫曼编码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

如果你之前没有做过数据压缩,或者想要了解数据压缩的原理,那么这编文章将会帮到你。这编文章将会带你彻底了解哈夫曼编码原理,这种编码方式常用作的图片无损压缩,和ZIP的等压缩存储。

思考,计算机的存储与解析获取

这里有一组数据为1, 3,4,5,6,1,4,3,5. 单位为字节,把他们存起来。那么二进制就是1,11,100,101,110,1,100,11, 101. 但是计算机存储的时候,他们每个数据占8个“格子” ,即为**00000001, 00000011,00000100,00000101,00000110,
00000001,00000100, 00000011,00000101.**真正存储的时候是没有分割区分的,数据都是放在一起的。000000010000001100000100000001010000011000000001000001000000001100000101 。那么是怎么识别获取的数据的呢? 读取的时候,每8个位置作为一个数据读取,如果是int类型,一般都是32位,即每32位作为一个数据。
即为

可见,前缀为00000这部分是无效数据,无疑会浪费了很大一部分空间。这种存储编码被成为定长编码。这是为什么会这样子存储?因为如果不固定长度,计算机就不会知道读的数据是什么。举个例子,1和3放在在一起为111,如果不固定位数,可能识别为3和1(11,1)也可以识别为1和3(1,11),甚至全部读取为一个数字为7(111)

那么有没有一种存储方式可以按需节约来存储呢?答案是

树的知识

我们先回顾下关于树的知识点,方便我们理解下面的内容。

叶子结点

叶子结点是指一个树形结构中,没有任何子结点的节点,也就是说它是树结构的最底层节点

在这里插入图片描述

什么是度?

当前结点的最大的子节点数目。也就是分支的数目。
在这里插入图片描述
如图,A的度为2, B的度为2. 而叶子结点的度为0. 由此可见,二叉树结点的最大的度为2.最小为0.

什么是路径,路径长度

路径: 是指从树中一个节点到另一个节点的分支所构成的路线。
路径长度: 从一个结点到另一个结点所经过的“边”的数量,被我们称为两个结点之间的路径长度。
在这里插入图片描述

例如:A到F的路径长度为2。A到H的路径长度为3

什么是权值

权值就是某个结点存储的数据的值。如下图,H结点存了一个数据是100,那么久叫他的权值为100
在这里插入图片描述

什么是带权路径长度

权路径长度是指根结点到某的结点的路径的长度和该结点的权值相乘的结果。
如上图, 根结点A到H的路径为3, 而H结点的权值为100,那么他的带权路径长度为3*100=300

哈夫曼编码

我们不急着怎么看他的定义,先通过例子去理解。

现在有个一串字母"ACCCCCABDDD",按照下面方式将它进行特殊存储
下面是字符对应二进制表格

字符二进制
A01000001
B01000010
C01000011
D01000100

第一步,将数据进行节约存储。

为了节约数据空间,我们把前面可以理解为多余的部分空间去掉,做个映射表,即为

字符二进制
A1
B10
C11
D100

第二步,统计每一个字符的出现个数

字符出现个数
A1
B2
C5
D3

第三步,按“出现个数”进行排序

字符出现个数
C5
D3
B2
A1

第四步,构建带权值的二叉树

将“出现个数”作为父结点权值(具体规则看下面步骤), 将字符二进制数据作为叶子结点权值,构建二叉树。将权值越大的,距离根节点越近,最大权值带权路径最短,以此例推。(如果忘记的概念,请到上面重复阅读)

(1)首先把最小的两个权值的作为叶子节点 ,出现次数大的在左边, 构建一个二叉树。如下图
在这里插入图片描述

(2)将这个新组成的二叉树他的父节点求权值,将A和B的权值相加,得到 3,如下
在这里插入图片描述

(3)将比A和B最近的数据进行构建新组合二叉树,刚刚好比A和B大的数据是D,将D与A,B的父节点,作为同一层构建二叉树,如下。

在这里插入图片描述

然后继续求顶部根节点的权值,将D的权值与A,B的父节点的权值相加求值。
在这里插入图片描述
依次类推,可以得出整棵树如下

在这里插入图片描述
然后,把除了叶子节点的权值全部改成1.

在这里插入图片描述

最后,叶子节点全部改成0,除B 外,B 改成1

在这里插入图片描述

第五步,制作代号表

把左边节点权值, 我们从顶点触发,把经过的叶子节点带权路径轨迹记录下来。

第一个为: 1 - 0
第二个为: 1 - 1 - 0
第三个为: 1 - 1 - 1 - 0
第四个为: 1 - 1 -1 - 1

由此可以推出

代号字母
10C
110D
1110A
1111B

没错,这时候你已经猜出来,为什么要这么做了。

第六步,存储

有了上面这个表格后,就可以存储和读取了。
字符串为:ACCCCCABDDD
那么按照上面的表格,分布存储为如下
1110 10 10 10 10 10 1110 1111 110 110 110

第七步,读取

我们需要根据这个树,通过轨迹来读取对于的值。
在这里插入图片描述
根节点出发,遇到1右边,遇到0左边
读取这串数据“1110 10 10 10 10 10 1110 1111 110 110 110”,如图
在这里插入图片描述
所以读取第一个值是A,(存储表的的时候是存二进制(1),这里只不过是为了好阅读)
剩下的数据为“ 10 10 10 10 10 1110 1111 110 110 110”,继续解析数据,如图

口诀: 遇到1右边,遇到0左边
在这里插入图片描述
剩下的数据为“10 10 10 1110 1111 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边

在这里插入图片描述
剩下的数据为“ 10 10 1110 1111 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边
在这里插入图片描述
剩下的数据为“ 10 1110 1111 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边
在这里插入图片描述
剩下的数据为“ 1110 1111 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边
在这里插入图片描述
剩下的数据为“ 1111 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边
在这里插入图片描述
剩下的数据为“ 110 110 110”,继续解析数据,如图,
口诀: 遇到1右边,遇到0左边
在这里插入图片描述

以此类推下去,全部都能解析出来。

这样的二叉树树,称为哈夫曼树。

下面是哈夫曼树的概念引用

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

由此,对比传统的存储二进制,可见节约了多少空间!通过这个规则,你已经知道为什么出现次数最多的要到前面,这样可以大大地提高读取效率。

有兴趣的朋友可以思考下图片的数据是怎么压缩的?欢迎到评论区 下留言哈哈。提示:一张图片可能有颜色值大量重复,比如一区域只有蓝色,其他全是红色的图片。

如果这篇文章有帮助到你,请点赞,评论,关注,收藏。

这篇关于7分钟0基础彻底理解常用数据压缩原理---哈夫曼编码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/740834

相关文章

Python中常用的四种取整方式分享

《Python中常用的四种取整方式分享》在数据处理和数值计算中,取整操作是非常常见的需求,Python提供了多种取整方式,本文为大家整理了四种常用的方法,希望对大家有所帮助... 目录引言向零取整(Truncate)向下取整(Floor)向上取整(Ceil)四舍五入(Round)四种取整方式的对比综合示例应

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha