数据结构学习笔记:利用哈夫曼编码实现文件的压缩与解压

原理:           

             利用哈夫曼树对文件中的字符进行重新编码,也就是根据文件中出现的所有字符的频率来创建哈夫曼树,然后生成哈夫曼编码来对文件中的所有字符进行重新编码,使文件中出现频率高的字符的编码变短,从而实现文件的压缩存储。相应的,解压过程也就是对文件按照哈夫曼编码的译码过程。

分析:

            无论是什么文件,它最终都是以二进制形式存储到硬盘中的。所以,我们在压缩文件时,可以将其按char 字符型来逐个读取,并记录该字符的出现频率,这样就可以根据字符及其频率表来创建哈夫曼树。

       压缩文件的一个难点在于,对字符重新编码后,新的字符编码必须以bit位的形式存入文件,但我们能操作的最小单位为1个字节,所以需要将新的编码用一个unsigned char 类型字符来间接储存。

例如,假设字符 'a' 的哈夫曼编码为 "01001",在存储时就可以 先声明一个 unsigned char 类型的数据 ch,并将其初始值设置为0 ,然后对 'a' 的编码进行遍历。

第一位编码为 '0' ,所以对 ch 左移一位:ch = ch << 1  ;

而第二个编码为 '1' ,则先将 ch 左移一位,然后将 ch 和 1 进行与操作 :ch = ch << 1 ;  ch = ch | 1 ;

依次类推,当 'a' 的编码遍历完时, ch 的二进制数据应为 "00001001" 。

此时, 'a' 的编码不足8位,则继续读取下一个字符的编码,然后将其以同样的方法存入 ch 中, 当 ch 存满8位时,就将 ch 存入目标文件中,再将 ch 重新清0,重复操作。 当然,在存储最后一个字符之后, ch 未填满,则需要在最后用 '0' 来补足8位。

数据结构学习笔记:利用哈夫曼编码实现文件的压缩与解压_第1张图片

数据结构学习笔记:利用哈夫曼编码实现文件的压缩与解压_第2张图片

压缩文件过程:

  1. 先扫描源文件,记录源文件中所有字符的出现频率以及源文件大小。(每次按char类型读取1个字节,然后根据读取字符的值将其频率存入拥有256个元素(最多有256种字符)的数组中)
  2. 根据字符频率生成哈夫曼树,并保存每个字符对应的哈夫曼编码。
  3. 打开目标文件,将源文件大小及源文件字符频率表存储到目标文件头。
  4. 再次扫描源文件,每读取一个字符都将其转换为对应的哈夫曼编码,并存入目标文件中。重复操作,直至将源文件扫描完毕。


解压文件过程:

  1.  扫描压缩文件。先读取文件头信息。根据文件字符频率表建立哈夫曼树并生成相应的哈夫曼编码。
  2. 打开解压文件,扫描压缩文件中的正文,每次读取一个字符,将其转换为二进制字符串。(linux c中没有现成的将字符值转换为二进制字符串的标准函数,需要自己编写),我试作了一个转换函数,如下:

数据结构学习笔记:利用哈夫曼编码实现文件的压缩与解压_第3张图片

然后扫描二进制字符串,进行译码工作。翻译过程有些类似于编码过程,每次翻译出一个字符就将其写入解压文件中。重复操作,直到压缩文件全部翻译完毕。

总结:

      利用哈夫曼编码实现的压缩文件程序,在压缩一些文本文件时压缩率较好,而在压缩其他文件,如图片或较大的文件时,会出现压缩率很差的问题。对于一些字符频率分布太过平均的极端情况,由于压缩时需要保存字符频率表,甚至会出现压缩文件比源文件大的现象。





你可能感兴趣的:(linux,c,数据结构,压缩,编码)