哈夫曼编码简介 -- 用最简单的方式说清楚哈夫曼压缩算法
来源:互联网 发布:c语言三维数组 编辑:程序博客网 时间:2024/06/05 20:58
哈弗曼编码几乎是所有压缩算法的基础,其实这个算法并不复杂,简单的理解就是,如何用更短的bit来编码数据。
我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit:
这样,计算机就能很方便的把由0和1组成的数据流解析成原始信息,但我们知道,在很多情况下,数据文件中的字符出现的概率是不均匀的,比如在一篇英语文章中,字母“E”出现的频率最高,“Z”最低,如果我们使用不定长的bit编码,频率高的字母用比较短的编码表示,频率低的字母用长的编码表示,岂不是可以大大缩小文件的空间吗?
但这就要求编码要符合“前缀编码”的要求,即较短的编码不能是任何较长的编码的前缀,这样解析的时候才不会混淆,比如下面的编码方法就符合前缀原则:
根据这个码表,下面一段数据就可以唯一解析成原始信息了:
1110010101110110111100010 – DABBDCEAAB
要生成这种编码,最方便的就是用二叉树,考察一下下面这个树
把要编码的字符放在二叉树的叶子上,所有的左节点是0,右节点是1,从根浏览到叶子上,因为字符只能出现在树叶上,任何一个字符的路径都不会是另一字符路径的前缀路径,符合前缀原则编码就可以得到
现在我们可以开始考虑压缩的问题,如果有一篇只包含这五个字符的文章,而这几个字符的出现的次数如下:
A: 6次
B : 15次
C: 2次
D : 9次
E: 1次
用过用定长的编码,每个字符3bit,这篇文章总长度为:
3*6 + 3*15 + 3*2 + 3*9 + 3*1 = 99
而用上面用二叉树生成的编码,总长度为:
2*6 + 3*15 + 2*2 + 2*9 + 2*1 = 80
显然,这颗树还可以进一步优化,使得编码更短,比如下面的编码
生成的数据长度为:
3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63
可以看出,构造更优的二叉树,原则就是权重越大的叶子,距离根应该越近,而我们的终级目标是生成“最优”的二叉树,最优二叉树必须符合下面两个条件:
- 所有上层节点都大于等于下层节点。
- 某节点,设其较大的子节点为m,较小的子节点为n,m下的任一层的所有节点都应大于等于n下的该层的所有节点。
上面这个例子是比较简单的,实际的文件中,一个字节有256种可能的取值,所以二叉树的叶子节点多达256个,最终的树形可能非常复杂,但有一种非常精巧的算法可以快速地建起一棵最优二叉树,这种算法由D.Huffman(戴?哈夫曼)提出,下面我们先来介绍哈弗曼算法的步骤,然后再来证明通过这么简单的步骤得出的树形确实是一棵最优二叉树。
哈夫曼算法的步骤是这样的:
比如上面的例子,哈弗曼树建立的过程如下:
1) 列出原始的节点数据:
2) 将最小的两个节点C和E结合起来:
3) 再将新的节点和A组合起来
4) 再将D节点加入
5) 如此循环,最终得到一个最优二叉树
生成的数据文件长度为:
3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63
下面我们用逆推法来证明对于各种不同的节点序列,用哈弗曼算法建立起来的树总是一棵最优二叉树:
- 当这个过程中的节点序列只有两个节点时(比如前例中的15和18),肯定是一棵最优二叉树,一个编码为0,另一个编码为1,无法再进一步优化。
- 然后往前步进,节点序列中不断地减少一个节点,增加两个节点,在步进过程中将始终保持是一棵最优二叉树,这是因为:
- 按照哈弗曼树的建立过程,新增的两个节点是当前节点序列中最小的两个,其他的任何两个节点的父节点都大于(或等于)这两个节点的父节点,只要前一步是最优二叉树,其他的任何两个节点的父节点就一定都处在它们的父节点的上层或同层,所以这两个节点一定处在当前二叉树的最低一层。
- 这两个新增的节点是最小的,所以无法和其他上层节点对换。符合我们前面说的最优二叉树的第一个条件。
- 只要前一步是最优二叉树,由于这两个新增的节点是最小的,即使同层有其他节点,也无法和同层其他节点重新结合,产生比它们的父节点更小的上层节点来和同层的其他节点对换。它们的父节点小于其他节点的父节点,它们又小于其他所有节点,只要前一步符合最优二叉树的第二个条件,到这一步仍将符合。
这样一步步逆推下去,在这个过程中哈弗曼树每一步都始终保持着是一棵最优二叉树。
- 哈夫曼编码简介 -- 用最简单的方式说清楚哈夫曼压缩算法
- 哈夫曼编码压缩算法
- Huffman(哈夫曼) 编码压缩算法
- Huffman(哈夫曼) 编码压缩算法
- 链路层的编码研究(2)最简单的编码方式
- 用C#压缩单个txt文件的最简单方式是什么
- 文件压缩与解压缩(哈夫曼编码压缩方式)
- C++实现图片压缩算法(哈夫曼编码)
- 几种排序算法的最简单实现方式
- 几种排序算法的最简单实现方式
- 用最简单的方式安装smokeping
- 如何使用java压缩文件夹成为zip包(最简单的方式 已测试)
- 基于哈夫曼编码的文件压缩解压
- 基于哈夫曼编码的文件压缩
- 基于哈夫曼编码的文件压缩
- 【简单向】用最简单易懂的方式实现FFT
- PCM编码压缩算法
- Huffman 编码压缩算法
- HEVC学习(八) —— 以SAO为例浅析跟踪代码方法
- 重叠字符串
- vb调用蜂鸣器制造音阶
- POJ2253 青蛙泡妞(单源最短路径变形)
- HEVC学习(九) —— 帧内预测系列之六
- 哈夫曼编码简介 -- 用最简单的方式说清楚哈夫曼压缩算法
- 编译HBase Source
- VxWorks移植到pc104
- HEVC学习(十) —— 与变换有关的几个主要函数及重要变量
- Linux可加载内核模块(LKM)
- 模拟AP与可以访问互联网的网络连接,虚拟出一个“无线路由器”
- HEVC学习(十一) —— 帧内预测系列之七
- C语言-字符串连接+字符串的复制
- HEVC学习(十二) —— CU的最终划分