基于C语言实现的文件压缩算法-哈夫曼编码

2023-11-20

哈夫曼编码,是一种数据压缩算法,通常用于无损数据压缩。该算法是由 David A. Huffman在麻省理工学院就读理学博士(Doctor of Science)的时候发明的,这位大佬在1952年发表了相关的一篇论文A Method for the Construction of Minimum-Redundancy Codes,有兴趣的朋友可以看看。


最近,我完成了一个银行客户安全管理系统的小组项目,该系统可以对文件进行压缩/解压,加密/解密,在加密和压缩的文件中进行搜索功能,以及根据数据库文件进行排序功能。我实现的部分是哈夫曼编码的压缩(Compression),解压(Decompression)算法,和搜索(Search)算法。现在在这里分享一下自己的学习心得。.


可变长度编码和前缀编码

在提出哈夫曼编码之前,我们先了解一下什么是可变长度编码和前缀编码。

当一个字符在文本中出现的频率比其他字符更频繁的时候,我们可以通过一种算法,这种算法可以使该字符以更少的位数(bit)表示相同的一段文本,这种方式即为可变长度编码(variable-length encoding)。比如,有些字符可以只用一一个二进制数(0或1)表示,有些字符用两个二进制数表示(01或10)。

假设有一个字符串"aaabbc",其中字符’a’,‘b’,'c’出现的频率依次是3,2,1,我们根据频率先随机给这四个字符定义四种编码,如下所示:

字符 编码
a 0
b 10
c 010

在编码后,这个字符串可表示为0001010010 (0 |0 |0 |10 |10 |010),看似对文本进行了压缩,当你对其解码的时候,会出现模棱两可的情形,如下所示:

0|0|0|10|10|010
aaabbc

0|0|0|10|10|0|10
aaabbab

为什么会出现歧义呢?因为该编码没有满足前缀编码原则(prefix rule),即一个字符的编码不能是另一个字符编码的前缀,根据上表,由于字符a的编码0是字符c的编码的前缀,所以在解码过程中会产生歧义。当遇到010编码的时候,就可能解码成字符ab(0|10)或者c(010)。


哈夫曼编码

哈夫曼编码(Huffman-Coding)是一种同时满足可变长度编码和前缀编码原则的算法。它可以通过连接具有不同权重的不同节点来构造哈夫曼树(最优二叉树),其中权重最小的节点远离根节点,权重最大的节点更靠近根节点。权值是根据字符在文本中出现的频率来决定。


算法步骤

哈夫曼树的构造采用自下而上的方法。

  1. 初始化所有叶子节点,每个叶子结点代表一个字符,其权重表示每个字符在文本中出现的频率。
  2. 每次选择权值最低的两个节点组成一个新节点,新节点的权重等于左右两颗子树的权重之和。
  3. 将这个新节点与其他叶节点进行比较,选择权重最小的两个节点(包括该新节点但是不包括其孩子结点),再构造成一个新节点。
  4. 重复步骤3,直至得到一颗完整的哈夫曼树。

举例

假设字符’a’,‘b’,‘c’,‘d’,'e’在文本中出现的频率依次为6,9,7,3,5

初始化所有叶节点如下:
在这里插入图片描述
选取两个最小权重的节点,生成一个新的节点,这里最小权重分别是3和5,因此生成一个权重为8的新节点。
在这里插入图片描述

接着继续选择两个最小权重的节点,由于3和5已经生成了新节点,所以不需要再拿3和5与其他节点进行比较。比较8,6,9,7,可知6和7最小,因此生成一个权重为13的新节点:

在这里插入图片描述

再拿剩下的节点8,13,9进行比较,发现8和9最小,因此生成一个权重为17的新节点:

在这里插入图片描述

最后将13和17生成一个权重为30的新节点,构成一颗完整的哈夫曼树如下,

在这里插入图片描述

根据哈夫曼编码”左0右1“的规则,依次表示路径和字符如下:

在这里插入图片描述

根据生成的哈夫曼树,我们可以通过根节点到叶子节点的路径得到每个字符的哈夫曼编码:

字符 编码
a 00
b 11
c 01
d 100
e 101

因此,原始的字符串就可以根据这个哈夫曼编码字典一一生成对应的编码,获得压缩后的编码。


代码运行

完整项目代码可参考我的github,其中文件project_dev1.cproject_dev2.c分别为哈夫曼编码的压缩和解压算法。

运行环境:
Linux系统,C90语言规范。

命令行指令:
make:执行makefile文件里面所有源代码的编译指令。
make clean:清除所有所有编译文件。
make cleanf:清除所有项目运行中产生的中间文件,比如压缩或者加密后的文件。
./main.out: 执行主程序

已给定的数据库文件:”Customer.txt",数据库文件内容如下所示:在这里插入图片描述

运行步骤:

  1. 命令行输入make编译所有源代码。
  2. 命令行输入./main.out运行主程序。
  3. 在用户界面选择"1. I want to compress the file"
    在这里插入图片描述
  4. 根据提示选择"1. I Efficient Compression",由于选项二是行程长度压缩算法(Run Length Encoding),相对而言没有哈夫曼编码压缩效率高(尤其在应对重复字符时)。接着输入你要解压的文件,这里可以压缩示例文件"Customer.txt"。或者用户自己创建文件进行压缩。
    在这里插入图片描述
  5. 解压时终端会输出根据哈夫曼树生成的哈夫曼编码以及压缩前后的二进制数,如下所示:
    在这里插入图片描述
  6. 运行完后,你可以在文件夹目录下看到两个导出的文件,其中"Huffman_Codes.txt"是压缩后的哈夫曼编码,"HFT_Model"是哈夫曼树模型,这个模型在解压缩的时候用得上。
    在这里插入图片描述
  7. 回到用户界面,选择"3. I want to decompress the file",然后输入你要解压缩的文件名"Huffman_Codes.txt",如下所示:
    在这里插入图片描述
  8. 该程序会将解压后的文件内容输入到终端上:
    在这里插入图片描述
    并且导出解压缩后的文件"HFT_Decompression.txt"到目录中:
    在这里插入图片描述
  9. 回到用户界面,你可以使用其他功能或者直接输入-1退出程序。然后依次输入make clean 和 make cleanf清楚编译文件和程序运行中产生的中间文件"Huffman_Codes.txt",“HFT_Model"和"HFT_Decompression.txt”。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于C语言实现的文件压缩算法-哈夫曼编码 的相关文章

随机推荐

  • 入门系列之使用Sysdig监视您的Ubuntu 16.04系统

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由乌鸦 发表于云 社区专栏 介绍 Sysdig是一个全面的开源系统活动监控 捕获和分析应用程序 它具有强大的过滤语言和可自定义的输出 以及可以使用称为chisels 的Lua脚本
  • 互补二元组

    时间限制 10000ms 单点时限 1000ms 内存限制 256MB 描述 给定N个整数二元组 X1 Y1 X2 Y2 XN YN 请你计算其中有多少对二元组 Xi Yi 和 Xj Yj 满足Xi Xj Yi Yj且i lt j 输入 第
  • 【试题】排列组合

    在写一个远程的代码 如果本地有M个显示器 远程有N个显示器 M lt N 依据分辨率 显示器刷新频率等要求 需要对远程的N个显示器进行最佳分辨率修改 之后 需要从N个远程显示器中选择M个 跟本地显示器进行一对一的匹配 即从 A N M N
  • 注意:怎么用JMeter操作MySQL数据库?看完秒懂!

    近期用JMeter做接口测试 遇到了一个需要用到数据数据库的场景 一个关于数据报告的页面 需要将数据库里面的数据求和或者取均值之后 展示出来 如果要断言的话 需要连接数据库 通过写sql语句 将sql查询结果与页面的结果进行对比 以MySQ
  • 微信pc端浏览器打开页面空白的问题

    今天写了一个web项目 用chrome浏览器 手机端微信你打开都没问题 但是在pc端微信打开后是空白的 于是我重新做了一个空白的vue项目 用pc端微信浏览器是可以打开的 慢慢调试发现是语法的问题 一步一步减去组件 再一步一步加上组件 最终
  • ubuntu运用软件和更新自动安装NVIDIA显卡驱动

    可能是我电脑硬件问题 直接运用软件和更新安装驱动 老是不能装成功 甚至装的系统都进不了 还要重装系统 这次重装系统后 我试着用软件和更新来自动安装驱动 一 secure boot修改为disable 1 首先进入终端输入 secure bo
  • error: (-209) The operation is neither ‘array op array‘ (where arrays have the same size and type)

    问题展示 error 209 The operation is neither array op array where arrays have the same size and type 错误原因 两个矩阵尺寸大小不一样 解决方法 指定
  • IDEA运行缓慢卡顿,解决idea卡顿,控制台中文乱码 以及其它常用设置

    IDEA运行缓慢卡顿 解决idea卡顿问题以及常用设置 IDEA卡顿原因 优化IDEA配置 重点推荐的方法 手动修改IDEA配置步骤 其他卡顿优化 参考 1 idea启动时会有两个快捷方式 2 卸载不需要用的插件 3 减少内存 4 适当关闭
  • HttpClient 简介说明

    转自 HttpClient 简介说明 下文笔者将讲述HttpClient框架的简介说明 如下所示 HttpCient简介说明 HttpClient是一个开源项目 它是Apache Jakarta Common下的一个子项目 HttpClie
  • Invalid Address specified to RtlValidateHeap

    Invalid Address specified to RtlValidateHeap VC编程 最后推出对话框的时候 会有错误提示声音 硄 但是没有弹出错误提示对话框 症状描述与下面的类似 声音就和Assertion Failure一样
  • html遍历数组,JS数组遍历的几种方式

    JS数组遍历 基本就是for forin foreach forof map等等一些方法 以下介绍几种本文分析用到的数组遍历方式以及进行性能分析对比 第一种 普通for循环 代码如下 for j 0 j lt arr length j 简要
  • 【三电平SVPWM学习

    导读 本期对三电平SVPWM的原理和建模做一个简单介绍 并与两电平SVPWM做了一个对比 后面把三电平的SVPWM运用到异步电机直接转矩控制中 看与传统的两电平SVPWM 控制性能是否得到改善 模型可分享 关注公众号 浅谈电机控制 留下邮箱
  • 八大排序算法(六)——优先队列、堆和堆排序

    6 1 API 优先队列是一种抽象数据类型 它表示了一组值和对这些值的操作 优先队列最重要的操作就是删除最大元素和插入元素 6 2 初级实现 6 2 1 数组实现 无序 或许实现优先队列最简单方法就是基于下压栈的代码 insert 方法的代
  • java通过文件路径读取该路径下的所有文件并将其放入list中

    java通过文件路径读取该路径下的所有文件并将其放入list中 java中可以通过递归的方式获取指定路径下的所有文件并将其放入List集合中 假设指定路径为path 目标集合为fileList 遍历指定路径下的所有文件 如果是目录文件则递归
  • 旋转链表(leetcode)

    61 旋转链表 给你一个链表的头节点 head 旋转链表 将链表每个节点向右移动 k 个位置 示例 1 输入 head 1 2 3 4 5 k 2 输出 4 5 1 2 3 示例 2 输入 head 0 1 2 k 4 输出 2 0 1 提
  • centos安装配置hadoop超详细过程(含故障排除)

    1 集群部署介绍 1 1 Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台 以Hadoop分布式文件系统 HDFS Hadoop Distributed Filesystem 和MapReduce Goog
  • 计算机科学丛书(2014-2018.Q1)

    ISBN 名称 作者 出版时间 978 7 111 53451 8 数学设计和计算机体系结构 原书第2版 美 戴维 莫尼 哈里斯 莎拉 L 哈里斯著 978 7 111 44075 8 嵌入式计算系统设计原理 美 Marilyn Wolf著
  • C#中string.Format输出内容中含有花括号的解决方法

    转载一篇 版权声明 本文为CSDN博主 九德真君 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net lzdidiv article details 69469
  • python matrix用法_numpy中matrix使用方法

    matrix T transpose 返回矩阵的转置矩阵 matrix H hermitian conjugate transpose 返回复数矩阵的共轭元素矩阵 matrix I inverse 返回矩阵的逆矩阵 matrix A bas
  • 基于C语言实现的文件压缩算法-哈夫曼编码

    哈夫曼编码 是一种数据压缩算法 通常用于无损数据压缩 该算法是由 David A Huffman在麻省理工学院就读理学博士 Doctor of Science 的时候发明的 这位大佬在1952年发表了相关的一篇论文A Method for