【Program】基于 Huffman 编码的文件压缩
文章目录
一、文件压缩
1.1 定义
文件压缩:在不丢失有用信息的前提条件下,缩减数据量以减少储存空间,提高其传输、储存和处理效率。换句话说文件压缩就是按照一定的算法对文件中数据进行重新组织,减少收据的冗余和存储空间的一种技术,用示意图表示如下图所示。

1.2 目的
那为什么要进行文件压缩呢?主要有以下几个方面的原因:
(1) 缩进数据储存容量,减少存储空间
(2) 提高数据传输的速度,减少带宽占用量,提高通信效率
(3) 对数据的一种加密保护,增强数据在传输过程中的安全性
1.3 压缩的分类

一般,有损压缩比无损压缩算法压缩率要高。
压 缩 率 = 压 缩 后 的 结 果 大 小 源 文 件 大 小 压缩率 = \frac{压缩后的结果大小 }{ 源文件大小} 压缩率=源文件大小压缩后的结果大小
1.4 压缩的原理
压缩的本质:让文件占用的空间变小,减小文件所占用的存储空间(必须能够解压缩)。
(1) 将专有名词采用固定短语代替
比如:中华人民共和国 -> 中国 -> 中华人民共和国;北京大学 -> 北大 -> 北京大学。
(2) 缩短文件中的重复数据(通用无损压缩算法)
采用 <举例,长度> 这个数据对来进行压缩,重复出现 3 次及以上进行替换,没有重复出现的内容,原封不动写入压缩文件中。比如:
mnoabczxyuvwabc123456abczxydefgh
压缩
mnoabczxyuvw(9,3)123456(18,6)defgh
解压缩
mnoabczxyuvwabc123456abczxydefgh
(3) 给文件中每个字符找一个更短的编码(通用无损压缩算法)
因为文件中的数据在磁盘中都是以字节的方式来进行存储,如果将原文件中的数据我那个文件中写的时候,每个字节如果能够找到更短的比特位来进行替换,则就可以达到压缩的目的。
等长编码 和 不等长编码:

可以看到不等长编码的方式可以达到更好的压缩率。这里的不等长编码其实是以字节和出现的次数作为叶子结点构建的一颗二叉树。

基于 Huffman 编码的文件压缩:
● 获取源文件中的每一个字节出现的次数
● 根据字节出现的频率,构建 Huffman 树
● 获取编码
● 使用获取到的字节编码对源文件进行改写
二、Huffman
2.1 定义
将带权路径长度 WPL 最短的二叉树称为 Huffman 树。带权路径:从二叉树的根结点到二叉树中所有叶结点的路径长度与相应权值的乘积之和。

WPL( a ) = 1 * 2 + 3 * 2 + 5 * 2 + 7 * 2 = 32
WPL( b ) = 1 * 2 + 3 * 3 + 5 * 3 + 7 * 1 = 33
WPL( c ) = 7 * 3 + 5 * 3 + 3 * 2 + 1 * 1 = 43
WPL( d ) = 1 * 3 + 3 * 3 + 5 * 2 + 7 * 1 = 29
因此,上图 d 的二叉树才能称得上 Huffman 树。
那么如何能够达到带权路径最短呢?
让权值大的结点靠近根节点,让权值小的节点远离根节点。
2.2 Huffman 树的构建
第一步: 由给定的 n 个权值 { w 1 , w 2 , w 3 , … , w n w_1, w_2, w_3, … , w_n w1,w2,w3,…,wn} 构建 n 棵只有根节点的二叉树森林 F = { T 1 , T 2 , T 3 , … , T n T_1, T_2 , T_3, … ,T_n T1,T2,T3,…,Tn}, 每棵二叉树 T i T_i Ti 只有一个带权值 w i w_i wi 的根节点,左右孩子均为空。
假设我们有 4 字符它们的权值分别为 { B: 3, A: 1, D: 7, C: 5 },我们来构造 Huffman 树。首先第一步构建 4 棵只有根节点的二叉树森林 F = { T 1 , T 2 , T 3 , T 4 T_1, T_2 , T_3,T_4 T1,T2,T3,T4 }。

第二步: 重复以下步骤,直到 F 中只剩下一棵树为止。
● 在 F 中选取两棵根节点权值最小的二叉树,作为左右子树构造一棵新的二叉树,新二叉树根节点的权值为其左右子树根节点的权值之和。
● 在 F 中删除这两棵二叉树。
● 把新的二叉树加入到 F 中。

那么使用什么来保存构建过程中的创建的这些二叉树呢?vector、map、堆?
要保存这些二叉树,只需要保存二叉树根节点的地址即可。又因为要在二叉树森林中不断的选取根节点权值最小的两颗二叉树,进行构造新的二叉树,所以保存二叉树最好的结构的是堆,采用优先级队列,其底层结构就是堆。(优先级队列默认情况下是大堆,这里我们需要创建的是小堆,因此这里需要特别注意)
三、压缩流程
第一步: 统计源文件中每个字节出现的次数;
第二步: 根据统计的结果创建 Huffman 树;
(1) 根据所给的权值创建 n 个只有根节点的二叉树森林 F;
(2) 循环进行以下操作,直至 F 中剩余一颗二叉树为止。
● 从 F 中获取根节点的权值最小的两颗二叉树;
● 以这两棵树作为左右子树创建一颗新的二叉树,其根节点的权值为左右孩子节点中权值之和;
● 将新的二叉树放回至 F 中。
第三步: 通过 Huffman 树来获取每个字节的编码;
第四步: 使用获取到的字节编码对源文件进行改写。
本文介绍了基于Huffman编码的文件压缩原理和流程。通过统计文件中每个字节的出现频率,构建Huffman树,从而为每个字节生成更短的编码,实现文件的无损压缩。文章还探讨了构建Huffman树的优先级队列方法。

4516

被折叠的 条评论
为什么被折叠?



