基于Huffman算法实现文件压缩解压缩(C语言)
一、实现步骤
- 统计源文件中字符种类和频率
- 建立Huffman编码树
- 生成Huffman编码表
- 压缩文件时,字符匹配编码,将编码写入压缩后文件
- 解压缩文件时,读取编码,匹配编码表中的字符,写入解压缩后的文件
二、读取文件
为了能够处理任何格式的文件,采用二进制方式读写文件,以一个无符号字符(unsigned char)的8位类型为一个处理单元,最多有0~255种,即256种。
三、字符频率的统计
两种方案:
- 链表存储,每扫描到一种新字符就动态分配内存。链表在需要时分配内存,这样节省内存,但是每读取一个字符就要扫描一次链表,当字符很多时,时间效率太低,最坏达到O(n^2)。
- 利用桶排序的思想。因为仅有256种字符,使用静态内存,定义一个长度为256的数组,数组下标对应字符种类,不需要扫描数组就可以找到每一类字符的位置,每次读取一个新字符时,根据下标直接将相应数组元素的频率加一,时间效率更好。因为不是每一种字符都会出现,所以,统计完字符频率后,对它进行排序,降序排列,将字符频率为0的元素删除。
四、建立Huffman森林
Huffman节点包含字符种类、权重、父节点和左右孩子的信息。对每一种字符,分别建立一棵单节点的Huffman树,权重取作该字符的频率。将每一个Huffman节点的成员进行初始化。
五、建立Huffman编码树
每次从Huffman森林中选取两棵根节点权重最小的树,创建一个新节点,并分别以这两棵树作为其左右子树,合并为一棵更高的树,新树根节点的权重取作二者权重之和,设置根节点的左右孩子和两棵子树的父亲信息。这一选取、合并的过程反复进行,每经过一轮迭代,Huffman森林中的树就减少一棵,当最终森林中仅包含一棵树时,就是Huffman编码树。
六、生成Huffman编码
每一类字符对应一个Huffman编码,从叶节点(字符所在节点)从下往上生成每一类字符的编码,左’0’右’1’。为了得到正确的编码,定义一个缓存字符数组,从后往前保存,然后从前往后将编码复制到对应的编码域中。对于缓存字符数组的大小,由于字符种类最多有256种,即建立的Huffman编码树最多有256个叶节点,即树的最大深度为255,编码最长是255,所以为缓存字符数组分配256个字节的空间,最后一位用于保存字符串结束标志’\0’。
七、文件压缩
上面建立编码树时以8位为一个单元编码,压缩时也以8位为一个处理单元。
首先,将字符种类、频率和编码表存储在压缩目标文件中,供解压时使用。
然后,以二进制形式打开源文件,每次读取一个8位的无符号字符,循环扫描匹配存储于Huffman编码树中编码,
由于编码长度不定,需要一个编码缓存,待编码满足8位后才写入,文件结束时缓存中可能不足8位,在后面补0,补足8位后写入文件。
在Huffman节点中,编码的每一位以字符形式保存,占用空间大,不可以直接写入压缩文件,需要转换为二进制形式写入。利用C语言的位操作,与、或、移位,来实现,每匹配一位,用‘或’操作存入低位,并左移1位,为下一位腾出位置,依此循环,满足8位就写入一次。
八、文件解压缩
以二进制形式打开压缩文件。
首先,读取文件前端的字符种类数目,据此分配内存空间,随后读取字符-编码表保存到分配的节点中,再读取文件长度
然后,以8位为单元,读取随后的编码匹配对应的字符,这里依然使用前面压缩时用的方法,即C语言的位操作,同0x80进行与操作,判断8位字符的最高位是否为’1’,对比一位后,左移一位,将最高位移除,次高位移到最高位,依次对比。这次是编码向字符反向对比,与压缩时相反,需要用读取的编码逐位与编码表中的编码进行对比,对比一位后,增加一位再对比,每次对比都是一个循环(与每个字符的编码对比),时间效率低。
将Huffman编码树保存在文件中,解码时,从树根到叶节点对比编码,只要按照编码对树进行遍历,到达叶节点后即是一个字符,然后返回根节点,继续下一次遍历,时间效率高。
然而树节点中有字符、编码、父亲、左右孩子,而且父亲和孩子都是整型,占用空间大,会导致压缩文件变大。可以只存储字符以及对应的频率,解码时读取字符频率序偶即可重建Huffman编码树,这样节省了空间。
虽然,重建Huffman编码树也要花费一定时间,但相对上面的与编码表匹配的方法,时间效率更高。
基于Huffman算法实现文件压缩解压缩(C语言)相关推荐
- 基于LZ77算法的文件压缩铺垫
基于Huffman算法和LZ77算法的文件压缩(四) 本文开始讲解LZ77算法,会用到哈希,哈希原理详解 我们在基于Huffman算法和LZ77算法的文件压缩(一)当中总体介绍了Huffman算法和L ...
- 基于Huffman算法的文件解压缩
基于Huffman算法和LZ77算法的文件压缩(三) 基于Huffman算法和LZ77算法的文件压缩(一)和 基于Huffman算法和LZ77算法的文件压缩(二)讲解Huffman压缩的基本原理和文件 ...
- 基于LZ77算法的文件压缩收尾
基于Huffman算法和LZ77算法的文件压缩(六) 前面基于Huffman算法和LZ77算法的文件压缩(四) 基于Huffman算法和LZ77算法的文件压缩(五) 已经充分讲解LZ77到基本原理和实 ...
- 基于LZ77算法的文件压缩
基于Huffman算法和LZ77算法的文件压缩(五) 基于Huffman算法和LZ77算法的文件压缩(四)已经讲解LZ77算法到基本原理和压缩过程. 本文详细讲解文件压缩过程当中的问题 一.文件压缩的 ...
- 基于Huffman树的文件压缩(详细)
文件压缩 开发平台:Visual Studio 2008 开发技术:哈夫曼树,堆排序 项目流程: (1)统计要压缩的文件中各字符出现的次数,利用数据结构中的小堆来构建Huffman树,每次在堆顶选出两 ...
- 基于LZ77算法的文件解压缩项目缺陷分析
基于Huffman算法和LZ77算法的文件压缩(七) 基于Huffman算法和LZ77算法的文件压缩(六)已经讲解完文件压缩的过程,本文讲解文件解压缩的过程和大文件处理方式 一.解压缩的流程 LZ77 ...
- 基于Huffman算法和LZ77算法的文件压缩的改进方向
基于Huffman算法和LZ77算法的文件压缩(八) 到这里已经简单实现基于Huffman算法和LZ77算法的文件压缩, GitHub源码:点我 根据基于Huffman算法和LZ77算法的文件压缩(七 ...
- 哈夫曼字符串编码c语言实现,基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(原创)...
本文首先简要阐述哈夫曼算法的基本思想,然后介绍了使用哈夫曼算法进行文件压缩和解压缩的 处理步骤,最后给出了C语言实现的文件压缩和解压缩的源代码. 哈夫曼算法的主要思想是: ①首先遍历要处理的字符串,得 ...
- huffman算法实现文件的压缩与解压
本文采用哈夫曼编码的方式进行文件的压缩和解压缩,主要原理是通过huffman编码来表示字符,出现次数多的编码短,出现次数少的编码长,这样整体而言,所需的总的bit位是减少的.但是当大部 ...
最新文章
- js 两行之间的设置间距_敲敲黑板 | 文字间距随意调
- C++ Primer 学习笔记(第四章:表达式)
- Reddit年度盘点:2019年最佳机器学习项目
- golang 覆盖写入文件 简介
- C# AndrewUtil.dll 在小博中发布分享(翻译组件)
- dhcp request汉字乱码分析
- 启用vsftpd服务
- 白话SpringCloud | 第五章:服务容错保护(Hystrix)
- 开源sip客户端 linux,开源SIP服务器 Kamailio
- 服务器双cpu性能强不,双CPU的电脑用起来,性能和功耗都是原来的两倍?
- 我在看着你呢——shiro学习
- 我学习图像处理的小结
- dism++封装系统使用教程_dism++封装系统使用教程_win7系统部署工具Dism的操作方法...
- 用VMWARE安装Mac OSX Tiger 10.4.4 X86
- 社会网络分析中的基本概念
- 7-14 设计一个风扇Fan类 (20 分)
- 力扣刷题 DAY_82 贪心
- 查询某个网址的服务器IP
- 算法学习系列(贪心算法)—机器人攀登问题
- 函数feof使用注意事项
热门文章
- Arcgis for JS实现台风运动路径与影像范围的显示
- protools监听_给新手写的万元录音设备选择2020系列(六)监听音箱/耳机
- C++实现积分函数(第一章)
- 【WebService】Caused by: org.apache.cxf.transport.http.HTTPException: HTTP respon ...
- iOS高德地图去logo
- 各种图片编码格式详解
- 从零开始学USB(一、基础知识1)
- html图片高度撑开,CSS背景图撑开盒子高度
- 利用Python(pyserial、minimalmodbus、modbus_tk)进行单片机通信
- ES5-ES6-ES7_字符串与JOSN格式的数据相互转换以及深度克隆新对象