基于Huffman树的文件压缩(详细)
文件压缩
开发平台:Visual Studio 2008
开发技术:哈夫曼树,堆排序
项目流程:
(1)统计要压缩的文件中各字符出现的次数,利用数据结构中的小堆来构建Huffman树,每次在堆顶选出两个出现次数较小的字符先进行构建,将它们相加的结果又放进堆里面,直到堆里面的数据被取完,这样字符出现次数多的离Huffman树的根节点就比较近,字符出现次数少的离Huffman树的根节点就比较远。
(2)根据构建好的Huffman树写出Huffman code,规定向左为“0”向右为“1”,这样字符出现次数多的Huffman code较短,字符出现次数少的Huffman code较长。
(3)根据Huffman code 对原文件进行压缩,因为Huffman code刚好为“0”、“1”序列,所以可以每8位为一个字节写进压缩文件中,当余下的位数不够8位写不成一个字节时,需要在后面补0够一个字节再写入,这样就完成了文件的压缩,但要注意后面补0的位数为文件解压缩留下了隐患。
(4)在上个步骤压缩时由于后面不够一个字节在后面补了0,但是在解压缩的时候我们并不知道在进行压缩的时候在后面到底补了多少位0,而且在进行解压缩的时候我们还是需要用到Huffman树的结构,这时候我就想到用一个配置文件来记录原文件字符出现的总次数和每个字符分别出现的次数,这样在解压缩的时候直接去配置文件中读取需要的信息即可。
(5)读取配置文件中存放的信息,再次构建Huffman树,读取压缩文件,从huffman树的根节点开始找,每次遇到叶子结点就停止,将叶子结点所对应的字符写进解压缩文件,注意这里不能将压缩文件全部读完,只需要还原配置文件中所记录的总的字符个数个即可,这就完成了文件的解压缩。
背景知识:
Huffman树,又称为最优二叉树,是加权路径最短的二叉树,权值较大的结点离根节点较近。
路径:树中一个节点到另一个节点之间的分支构成这两个节点之间的路径。
路径长度:路径上的分支数目称作路径长度。
树的路径长度:从树的根节点到每一个节点的路径长度之和。
结点的带权路径长度:在一棵树中,如果其节点上附带有一个权值,通常把该节点的路径长度与该节点上的权值之积称为该结点的带权路径长度。
贪心算法:是指在问题求解时,总是做当前看起来最好的选择,也就是说贪心算法做出的不是整体最优的选择,而是某种意义上的局部最优解。
- 使用贪心算法构建Huffman树:
思想:每次从数组中取出两个当前权值最小的数去创建,并作为叶子结点,它们的根节点的权值是两者之和,把它们的根节点再放回数组,再选出当前数组中两个权值最小的数创建,直到数组的数选完。
- 根据Huffman树生成Huffman编码
可以看到,权值越小的,它的Huffman编码越长,权值越大的,它的Huffman编码越短。那么如何运用到文件压缩中呢?
我们来分析一个文件,假设一个文件的内容是“abbcccdddd”,“a”出现的次数是1次,“b”出现的次数是2次,“c”出现的次数是3次,“d”出现的次数是4次,现在以各字符出现的次数构建一个Huffman树,并为各字符编码,如下图所示:
写出每个字符所对应的Huffman编码:
‘a’:100 ‘b’:101 ‘c’:11 ‘d’:0
根据每个字符的huffman编码对照原文件字符出现的顺序写出Huffman code:1001011011111110000
这里的0或者1代表一个二进制位,那么压缩文件是多大呢?
我们可以看到,Huffman code 一共19个比特位,每8位为一个字节写入压缩文件,当余下的不够一个字节时,在后面补0够一个字节再写入,这里需要补上5个0总共3个字节,而原文件是10个字节,很明显少了7个字节,这就是文件压缩的原理。
项目主要思路:
1.统计:首先读取一个文件,统计出256个字符中各字符出现的次数以及字符出现的总次数;
2.建树:按照字符出现的次数,并以次数作为权值建立huffman树,根据所构建的huffman树生成huffman编码;
3.压缩:再次读取原文件,按照该字符对应的编码压缩文件;
4.加工:将字符出现的总次数以及各个字符出现的次数写进配置文件;
5.解压:利用压缩文件以及配置文件恢复原文件;
6.测试:首先对压缩和解压缩两个功能进行测试,看压缩后的文件是否比原文件小,以及解压缩文件与原文件的大小一致;在这个基础上再验证解压缩文件与原文件的内容是否保持一致,这里采用 beyond compare 软件来对文件内容进行验证,这样才验证了程序的大概功能是正确的。其次是压缩不同大小的文件计算出压缩所需要的时间来考量压缩的性能;
7.计算:经过多次压缩不同大小的文件不同类型的文件来计算文件的压缩率;
8.时间:使用 GetTickcount 函数计算完成压缩或者解压缩所需要的时间,GetTickcount 函数它返回从操作系统启动到当前所经过的毫秒数,常常用来判断某个方法执行的时间。
项目源码:https://github.com/YPT-victory/FileCompress.git
运行结果:
测试用例:
下面是对于不同类型的文件进行压缩和解压缩的文件详情:
由于beyond compare 对于图片文件和音频文件不识别,这里只能通过人工的方法进行验证,因为在进行解压缩的时候加了后缀信息,所以在进行验证的时候需要将后缀修改为和原文件类型相同的后缀再去打开,通过验证得出结论:图片文件和音频文件也能够正常压缩和解压缩。
思考:
- 为什么要使用配置文件?
答:(1)在项目中,有这样一个步骤就是将字符对应的编码转化为位,每8位转换为一个字节写入压缩文件,在转换过程中可能余下的位数不够8位,所以就需要在其后面补0将其填充至一个字节再写入,这里所补的0的个数是不固定的,为了在解压缩的时候能够正确的解压缩,所以就需要将原文件中字符的总个数记录下来以供解压缩使用。
(2)还有一点就是在解压缩的时候光有解压缩文件和字符出现的总个数是不够的,还需要用到Huffman树的结构,要构建Huffman树就需要用到每个字符出现的次数,而每个字符出现的次数需要遍历原文件才能获得,但是一般在解压缩的时候原文件是不存在的,所以就想到把每个字符出现的次数也写进配置文件里,在进行解压缩的时候去配置文件中获取该信息重新构建Huffman树即可。
还会持续更新~~~
基于Huffman树的文件压缩(详细)相关推荐
- 【小项目】用Huffman树实现文件压缩并解压
一.前言 如果你学习数据结构,就一定会学到Huffman树,而Huffman编码实际上上就是zip压缩的核心部分,所以,如果已经学习了Huffman树,为何不尝试写一个压缩程序出来呢? 如果你没有学习 ...
- 基于Huffman算法实现文件压缩解压缩(C语言)
一.实现步骤 统计源文件中字符种类和频率 建立Huffman编码树 生成Huffman编码表 压缩文件时,字符匹配编码,将编码写入压缩后文件 解压缩文件时,读取编码,匹配编码表中的字符,写入解压缩后的 ...
- 基于LZ77算法的文件压缩铺垫
基于Huffman算法和LZ77算法的文件压缩(四) 本文开始讲解LZ77算法,会用到哈希,哈希原理详解 我们在基于Huffman算法和LZ77算法的文件压缩(一)当中总体介绍了Huffman算法和L ...
- 基于LZ77算法的文件压缩
基于Huffman算法和LZ77算法的文件压缩(五) 基于Huffman算法和LZ77算法的文件压缩(四)已经讲解LZ77算法到基本原理和压缩过程. 本文详细讲解文件压缩过程当中的问题 一.文件压缩的 ...
- 基于Huffman算法的文件解压缩
基于Huffman算法和LZ77算法的文件压缩(三) 基于Huffman算法和LZ77算法的文件压缩(一)和 基于Huffman算法和LZ77算法的文件压缩(二)讲解Huffman压缩的基本原理和文件 ...
- BUAA数据结构作业——基于Huffman码的文件压缩工具
目录 前言 题目 问题描述 输入形式 输出形式 样例 问题分析 代码实现 前言 大家好哇!今天给大家分享一道Huffman码的实战应用题.Huffman码来源于Huffman树,假设二叉树有m个叶结点 ...
- 基于LZ77算法的文件压缩收尾
基于Huffman算法和LZ77算法的文件压缩(六) 前面基于Huffman算法和LZ77算法的文件压缩(四) 基于Huffman算法和LZ77算法的文件压缩(五) 已经充分讲解LZ77到基本原理和实 ...
- 哈夫曼树实现文件压缩
最近在学了哈夫曼树之后,作为练习,写了一个文件压缩的小项目: 在这里和大家分享一下: 主要实现思路: 利用哈夫曼树的特性对字符进行哈夫曼编码,其中运用到了最小堆:利用最小堆的特性,找出构造哈夫曼树的结 ...
- c语言文件压缩与解压缩实验报告,哈弗曼树的文件压缩和解压实验报告(C语言).doc...
Lab05 树结构的应用 学号: 姓名: 实验时间:2011.5.24 1.问题描述 哈弗曼树的编码与译码 - 功能:实现对任何类型文件的压缩与解码 - 输入:源文件,压缩文件 - 输出:解码正确性判 ...
最新文章
- RabbitMQ Topic exchange
- 035、Linux下Dmidecode查看硬件信息
- 关于 AfxSocketInit() 的使用
- 中怎么均化走线_PCB板上多长的走线才是传输线?答案是……
- html 定时刷新 数据,js中,设置定时器 每隔几秒刷新一次页面数据
- 词云(WordCloud)制作
- python导入gif_Python之GIF图倒放,沙雕快乐源泉!我已经笑了一天了!
- C++学习之Dev-C++安装与调试
- 计算机原理与技术索引的应用,经常学一点计算机底层原理系列之索引
- java eclipse svn_[Java教程]Eclipse 安装 SVN 的在线插件
- Python3 解释器
- Java程序员须知的七个日志管理工具
- samba服务端配置和客户端使用【含windows共享文件到linux】
- tween.js--使用/教程/实例
- 信息安全工程师(软考中级)
- 小技巧,windows电脑上多开软件的办法
- 第十单元---前后连调
- centos7重装python_centos7.6删除重新安装python和yum
- 实战演练 Navicat 中英文模式切换
- 视频直播系统开发架构分析,视频直播系统架构技术应用层面