一、基本原理
1.Huffman编码算法
()统计频率:将文件以ASCII字符流的形式读入,统计每个符号的发生频率;
(2)排序:将所有文件中出现过的字符按照频率从小到大的顺序排列;
(3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较;重复此步骤,直到最后得到和为1的根节点;
(4)编码:将形成的二叉树的左节点标0,右节点标1,把从最上面的根节点到最下面的叶子节点途中遇到的0、1序列串起来,得到了各个字符的编码表示。
2.Huffman编码的数据结构设计
(1)Huffman节点结构
typedef struct huffman_node_tag
{
unsigned char isLeaf;//是否为叶节点,1是0不是
unsigned long count;//信源中出现频数
struct huffman_node_tag *parent;//父节点指针
union
{
struct//如果不是节结点,则此项为该节点左右子节点的指针
{
struct huffman_node_tag *zero, *one;//指向子节点,左0右1
};
unsigned char symbol;//如果是叶节点,则为某个信源符号
};
} huffman_node;
(2)Huffman码结构
typedef struct huffman_code_tag
{
/* The length of this code in bits. */
unsigned long numbits;//码字的长度
/* 码字的第1位存于bits[0]的第1位,
码字的第2位存于bits[0]的第2位,
码字的第8位存于bits[0]的第8位,
码字的第9位存于bits[1]的第1位*/
unsigned char *bits;
} huffman_code;
二、实验流程及代码分析
1.Huffman编码流程
(1)读入待编码的源文件
int
main(int argc, char** argv)
{
char memory = 0;//是否对内存数据进行操作,1操作,0不操作
char compress = 1;//compress为1解码,0编码
int opt;
const char *file_in = NULL, *file_out = NULL;
//step1:add by yzhang for huffman statistics
const char *file_out_table = NULL;
//end by yzhang
FILE *in = stdin;
FILE *out = stdout;
//step1:add by yzhang for huffman statistics
FILE * outTable = NULL;
//end by yzhang
/* Get the command line arguments. */
while((opt = getopt(argc, argv, "i:o:cdhvmt:")) != -1) //读取命令行参数
{
switch(opt)
{
case 'i':
file_in = optarg;//i 输入文件
break;
case 'o':
file_out = optarg;//o 输出文件
break;
case 'c':
compress = 1;//c 编码
break;
case 'd':
compress = 0;//d 解码
break;
case 'h':
usage(stdout);//h 输出参数用法的说明
return 0;
case 'v':
version(stdout);//v 输出版本号的信息
return 0;
case 'm':
memory = 1;//m 对内存数据进行操作
break;
// by yzhang for huffman statistics
case 't':
file_out_table = optarg;//t 输出中间数据信息
break;
//end by yzhang
default:
usage(stderr);
return 1;
}
}
/* If an input file is given then open it. */
if(file_in)//读取输入文件
{
in = fopen(file_in, "rb");
if(!in)
{
fprintf(stderr,
"Can't open input file '%s': %s\n",
file_in, strerror(errno));
return 1;
}
}
/* If an output file is given then create it. */
if(file_out)//创建输出文件
{
out = fopen(file_out, "wb");
if(!out)
{
fprintf(stderr,
"Can't open output file '%s': %s\n",
file_out, strerror(errno));
return 1;
}
}
//by yzhang for huffman statistics
if(file_out_table)
{
outTable = fopen(file_out_table, "w");
if(!outTable)
{
fprintf(stderr,
"Can't open output file '%s': %s\n",
file_out_table, strerror(errno));
return 1;
}
}
//e