一、实现步骤

  1. 统计源文件中字符种类和频率
  2. 建立Huffman编码树
  3. 生成Huffman编码表
  4. 压缩文件时,字符匹配编码,将编码写入压缩后文件
  5. 解压缩文件时,读取编码,匹配编码表中的字符,写入解压缩后的文件

二、读取文件

为了能够处理任何格式的文件,采用二进制方式读写文件,以一个无符号字符(unsigned char)的8位类型为一个处理单元,最多有0~255种,即256种。

三、字符频率的统计

两种方案:

  1. 链表存储,每扫描到一种新字符就动态分配内存。链表在需要时分配内存,这样节省内存,但是每读取一个字符就要扫描一次链表,当字符很多时,时间效率太低,最坏达到O(n^2)。
  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语言)相关推荐

  1. 基于LZ77算法的文件压缩铺垫

    基于Huffman算法和LZ77算法的文件压缩(四) 本文开始讲解LZ77算法,会用到哈希,哈希原理详解 我们在基于Huffman算法和LZ77算法的文件压缩(一)当中总体介绍了Huffman算法和L ...

  2. 基于Huffman算法的文件解压缩

    基于Huffman算法和LZ77算法的文件压缩(三) 基于Huffman算法和LZ77算法的文件压缩(一)和 基于Huffman算法和LZ77算法的文件压缩(二)讲解Huffman压缩的基本原理和文件 ...

  3. 基于LZ77算法的文件压缩收尾

    基于Huffman算法和LZ77算法的文件压缩(六) 前面基于Huffman算法和LZ77算法的文件压缩(四) 基于Huffman算法和LZ77算法的文件压缩(五) 已经充分讲解LZ77到基本原理和实 ...

  4. 基于LZ77算法的文件压缩

    基于Huffman算法和LZ77算法的文件压缩(五) 基于Huffman算法和LZ77算法的文件压缩(四)已经讲解LZ77算法到基本原理和压缩过程. 本文详细讲解文件压缩过程当中的问题 一.文件压缩的 ...

  5. 基于Huffman树的文件压缩(详细)

    文件压缩 开发平台:Visual Studio 2008 开发技术:哈夫曼树,堆排序 项目流程: (1)统计要压缩的文件中各字符出现的次数,利用数据结构中的小堆来构建Huffman树,每次在堆顶选出两 ...

  6. 基于LZ77算法的文件解压缩项目缺陷分析

    基于Huffman算法和LZ77算法的文件压缩(七) 基于Huffman算法和LZ77算法的文件压缩(六)已经讲解完文件压缩的过程,本文讲解文件解压缩的过程和大文件处理方式 一.解压缩的流程 LZ77 ...

  7. 基于Huffman算法和LZ77算法的文件压缩的改进方向

    基于Huffman算法和LZ77算法的文件压缩(八) 到这里已经简单实现基于Huffman算法和LZ77算法的文件压缩, GitHub源码:点我 根据基于Huffman算法和LZ77算法的文件压缩(七 ...

  8. 哈夫曼字符串编码c语言实现,基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(原创)...

    本文首先简要阐述哈夫曼算法的基本思想,然后介绍了使用哈夫曼算法进行文件压缩和解压缩的 处理步骤,最后给出了C语言实现的文件压缩和解压缩的源代码. 哈夫曼算法的主要思想是: ①首先遍历要处理的字符串,得 ...

  9. huffman算法实现文件的压缩与解压

            本文采用哈夫曼编码的方式进行文件的压缩和解压缩,主要原理是通过huffman编码来表示字符,出现次数多的编码短,出现次数少的编码长,这样整体而言,所需的总的bit位是减少的.但是当大部 ...

最新文章

  1. js 两行之间的设置间距_敲敲黑板 | 文字间距随意调
  2. C++ Primer 学习笔记(第四章:表达式)
  3. Reddit年度盘点:2019年最佳机器学习项目
  4. golang 覆盖写入文件 简介
  5. C# AndrewUtil.dll 在小博中发布分享(翻译组件)
  6. dhcp request汉字乱码分析
  7. 启用vsftpd服务
  8. 白话SpringCloud | 第五章:服务容错保护(Hystrix)
  9. 开源sip客户端 linux,开源SIP服务器 Kamailio
  10. 服务器双cpu性能强不,双CPU的电脑用起来,性能和功耗都是原来的两倍?
  11. 我在看着你呢——shiro学习
  12. 我学习图像处理的小结
  13. dism++封装系统使用教程_dism++封装系统使用教程_win7系统部署工具Dism的操作方法...
  14. 用VMWARE安装Mac OSX Tiger 10.4.4 X86
  15. 社会网络分析中的基本概念
  16. 7-14 设计一个风扇Fan类 (20 分)
  17. 力扣刷题 DAY_82 贪心
  18. 查询某个网址的服务器IP
  19. 算法学习系列(贪心算法)—机器人攀登问题
  20. 函数feof使用注意事项

热门文章

  1. Arcgis for JS实现台风运动路径与影像范围的显示
  2. protools监听_给新手写的万元录音设备选择2020系列(六)监听音箱/耳机
  3. C++实现积分函数(第一章)
  4. 【WebService】Caused by: org.apache.cxf.transport.http.HTTPException: HTTP respon ...
  5. iOS高德地图去logo
  6. 各种图片编码格式详解
  7. 从零开始学USB(一、基础知识1)
  8. html图片高度撑开,CSS背景图撑开盒子高度
  9. 利用Python(pyserial、minimalmodbus、modbus_tk)进行单片机通信
  10. ES5-ES6-ES7_字符串与JOSN格式的数据相互转换以及深度克隆新对象