哈夫曼算法进行文件压缩和解压缩
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本文首先简要阐述哈夫曼算法的基本思想,然后介绍了使用哈夫曼算法进行文件压缩和解压缩的
处理步骤,最后给出了C语言实现的文件压缩和解压缩的源代码。
哈夫曼算法的主要思想是:
①首先遍历要处理的字符串,得到每个字符的出现的次数;
②将每个字符(以其出现次数为权值)分别构造为二叉树(注意此时的二叉树只有一个节点);
③取所有二叉树种种字符出现次数最小的二叉树合并为一颗新的二叉树,新二叉树根节点的权值等于两个子节点的权值之和,新节点中的字符忽略;
④重复过程③直到所有树被合并为同一棵二叉树
⑤遍历最后得到的二叉树,自顶向下按路径编号,指向左节点的边编号0,指向右节点的边编号1,从根到叶节点的所有边上的0和1链接起来,就是叶子节点中字符的哈夫曼编码。
下图展示了哈夫曼编码的基本思想。
基于哈夫曼算法的文件压缩和解压缩过程分别说明如下:
一、文件压缩:
①统计词频:读取文件的每个字节,使用整数数组int statistic[MAX_CHARS]统计每个字符出现的次数,
由于一个字节最多表示2^8-1个字符,所以MAX_CHARS=256就足够了。在统计字符数的时候,
对于每一个byte, 有statistic[(unsigned char)byte]++。
②构造哈夫曼树:根据statistic数组,基于哈夫曼树算法造哈夫曼树,由于构造的过程中每次都要取最小权值的字符,
所以需要用优先队列来维护每棵树的根节点。
③生成编码:深度优先遍历哈弗曼树,得到每个叶子节点中的字符的编码并存入字符串数组char *dictionary[MAX_CHARS];
④存储词频:新建存储压缩数据的文件,首先写入不同字符的个数,然后将每个字符及其对应的词频写入文件。
⑤存储压缩数据:再次读取待压缩文件的每个字节byte,由
dictionary[(unsigned int)byte]得到对应的编码(注意每个字符
编码的长度不一),使用位运算一次将编码中的每个位(BIT)设置到一个char 类型的位缓冲中,可能多个编码才能填满一个
位缓冲,每填满一次,将位缓冲区以单个字节的形式写入文件。当文件遍历完成的时候,文件的压缩也就完成了。
二、文件解压:
①读取词频:读取压缩文件,将每个字符的出现次数存入数组statistic
②构造哈夫曼编码树:根据statistic数组构造哈夫曼编码树
③继续读取压缩文件,对于每个字节,使用位运算得到每个位(BIT)。对于每个BIT,根据BIT从根开始遍历哈夫曼树,如果BIT是0就走左分支,如果BIT 是1就走有分支,走到叶子节点的时候,输出对应的字符。走到叶子节点后,重新从哈夫曼树根节点开始匹配每个位。当整个压缩文件读取完毕时,文件解压缩也完成了。
上文介绍了基于哈夫曼算法的文件压缩和解压缩,下面给出基于上述思想的C 语言源代码,一共有5个文件,其中pq.h和pq.c
是优先队列,compress.h和compress.c是压缩和解压缩的实现,main.c是测试文件。
pq.h和pq.c请参见《优先队列(priority_queue)的C语言实现》:
/gropefor/blog/item/7d958eb68359cbe230add14e.html 另外三个文件内容如下:
* File: compress.h
* Purpose: To compress file using the Haffman algorithm
* Author: puresky
* Date: 2011/05/01
*/
#ifndef _FILE_COMPRESSION_H
#define _FILE_COMPRESSION_H
//Haffuman Tree Node
typedef struct HaffumanTreeNode HTN;
struct HaffumanTreeNode
{
char _ch; //character
int _count; //frequency
struct HaffumanTreeNode *_left; //left child
struct HaffumanTreeNode *_right;//rigth child
};
//FileCompress Struct
#define BITS_PER_CHAR 8 //the number of bits in a char
#define MAX_CHARS 256 //the max number of chars
#define FILE_BUF_SIZE 8192 //the size of Buffer for FILE I/O
typedef struct FileCompressStruct FCS;
struct FileCompressStruct
{
HTN *_haffuman; //A pointer to the root of hafumman tree unsigned int _charsCount; //To store the number of chars
unsigned int _total; //Total bytes in a file.
char *_dictionary[MAX_CHARS]; //to store the encoding of each character
int _statistic[MAX_CHARS]; //To store the number of each character };
FCS *fcs_new();
void fcs_compress(FCS *fcs, const char *inFileName, const char
*outFileName);
void fcs_decompress(FCS *fcs, const char *inFileName, const char
*outFileName);
void fcs_free(FCS *fcs);
#endif