Huffman压缩
数据结构 大作业一
一、问题描述
在合适的情况下,利⽤ Huffman 编码对⽂件进⾏压缩可以减少其占⽤空间,同时在需要使⽤到⽂件的 时候也可以根据压缩⽂件中所提供的信息来将其还原为原⽂件。本次实验中,我们将实现⼀个基于 Huffman 编码的⽂件压缩/解压缩⼯具。
二、基本要求
基于 Huffman 编码实现⼀个压缩器和解压缩器(其中 Huffman 编码以字节作为统计和编码的基本符号 单元),使其可以对任意的⽂件进⾏压缩和解压缩操作。针对编译⽣成的程序,要求压缩和解压缩部分 可以分别独⽴运⾏。具体要求为:
- 每次运⾏程序时,⽤⼾可以指定只压缩/只解压缩指定路径的⽂件。实现的时候不限制与⽤⼾的交 互⽅式,可供参考的⽅式包括但不限于
- 根据命令⾏参数指定功能(压缩/解压缩)和输⼊/输出⽂件路径
- GUI 界⾯
- 运⾏程序后由⽤⼾交互输⼊指定功能和路径
【CAUTION!】不被允许的交互⽅式: 通过修改源代码指定功能和⽂件路径
压缩时不需要指定解压⽂件的⽬标路径,解压缩时不需要指定压缩前原⽂件的路径,压缩后的⽂件 可以换到另⼀个位置再做解压缩
三、程序能实现的功能
- 压缩指定路径的任意格式的文件
- 解压指定路径的文件(无损)
- 可以选择压缩的基本单元(0.5Byte ~ 4Byte)
- 可以选择使用多元 Huffman 数进行压缩 (2~16)
- 3,4 项同时使用
四、实验思路
- 压缩
- 第一遍扫描文件,根据用户选择的压缩基本单元,统计每一种基本单元出现的频次
- 以出现的频次作为权重,根据用户选择构建 Huffman 树,若用户选择多元压缩,则首先补全节点数,其次使用优先队列,每次弹出最小的元素,构造 Huffman 树
- 根据构造出的 Huffman 树,求得 Huffman 编码 (压缩单元较小时,使用指针 new 内存的形式加速,压缩单元较大时,使用 map 来控制内存的使用)
- 首先输出被压缩文件的类型,压缩时使用的基本单元大小,Huffman 树种类,再输出每一个基本单元出现的频次
- 再次扫描文件,每当获取一个基本单元大小的字节,二进制输出它的 Huffman 编码 (每八位以一个字符的形式输出)
- 解压
- 首先获得压缩文件头部的相关信息,以及各个基本单元出现的频次
- 用和压缩时完全相同的方式构造出 Huffman 树,获得 Huffman 编码
- 扫描剩下的文件内容,根据二进制编码,转化为原来的基本单元输出
五、项目结构
1 | ─ huffman-compress |
六、关键内容实现
1. huffman树的建立
1 | //初始化 huffman树 |
2. 获取huffman编码
1 | char *cd = new char[fre]; |
3. 压缩
1 | while (infile.get(c)) |
4. 解压
1 | while (1) |
七、编译过程
编译环境
- Ubuntu-20.04 ( wsl2 )
- gcc 9.3.0
- cmake version 3.16.3
CMakeLists.txt (注意修改 Debug 模式和 Release 模式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24cmake_minimum_required(VERSION 3.5)
project(yasuo)
set (CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread" )
set(SOURCES
src/main.cpp
src/big.cpp
src/small.cpp
src/tempwindow.cpp
src/huffman.cpp)
add_definitions(-w)# system忽略了返回值,消除编译警告
add_executable(yasuo ${SOURCES})
SET(CMAKE_BUILD_TYPE "Release")
target_include_directories(yasuo
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include)编译操作(Release 版本为例,首先进入项目目录)
1
2
3
4
5
6mkdir Release
cd Release
cmake ..
make
./yasuo
# 运行程序
八、运行效果
使用 1.5Byte 为基本单元,三叉 Huffman 树压缩 png 文件,源文件 258kb,压缩后 182kb,解压后 258kb,效果较为明显,同时文件解压后无任何变化
性能测试
使用该程序压缩大小 1.3G 的 txt 文档
压缩用时:130.917s
解压用时:113.172s
压缩效率:
九、关于 Huffman 压缩的探索
压缩一包含中英文及数字的 txt 文档,压缩效果如下(压缩率=)
利用上述数据作图 (mathematica 作图有一定偏差)
根据上述实验数据可以看出:
- 压缩基本单元为 0.5Byte 时,基本没有压缩效果
- 随着压缩基本单元的增大,压缩效果总体上呈现上升趋势
- 在压缩的基本单元从 3.0Byte 变为 3.5Byte 时,压缩效果均有小幅下降
- 当选用叉 Huffman 树时,压缩效果明显更佳,而当选用叉 Huffman 树时,压缩效果较差 (叉 Huffman 树每一个节点都刚好可以利用 bit 的 Huffman 编码)
因此,在压缩 txt 文本文件时,选用叉 Huffman 树,在综合时间的情况下选择更大的压缩基本单元,能够提高压缩效率同时值得指出的是,对于图片,视频等文件类型,基本单元极有可能发生出现次数相近的情况,此时综合时间等考虑,可以尽量选择 1Byte 为压缩的基本单元