Huffman编解码

本文详细介绍了Huffman编码的原理,包括统计符号概率、构建Huffman树及编码过程。同时,阐述了编码流程,从读取文件、统计字符概率到建立码树、生成码字。此外,还分析了解码过程,以及在实验中遇到的错误和解决方法。通过10种不同格式文件的压缩实验,展示了Huffman编码在数据压缩中的应用和效果。
摘要由CSDN通过智能技术生成

一,实验原理

1,Huffman编码原理:

1)统计:将每个符号出现的概率进行统计,并且从小到大排序。

2)合并:将出现概率最小的两个符号概率进行合并,反映在二叉树上:将两个树叶节点合并得到一个父节点。重复此步骤直到根节点。

3)编码:二叉树按照左0右1的规则编码,遍历整棵树,然后自根节点向下到每个树叶节点,可以得到每个树叶节点的编码。

2,基本数据格式定义:

节点和码字的定义见代码。

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;

typedef struct huffman_code_tag//码表的定义
{
	/* The length of this code in bits. */
	unsigned long numbits;

	/* The bits that make up this code. The first
	   bit is at position 0 in bits[0]. The second
	   bit is at position 1 in bits[0]. The eighth
	   bit is at position 7 in bits[0]. The ninth
	   bit is at position 0 in bits[1]. */
	unsigned char *bits;
} huffman_code;

二,实验流程及代码分析

1,Huffman编码流程

1)读入文件

2)第一次扫描文件,统计文件中各个字符出现的概率

3)建立码树

4)将码表写入文件

5)第二次扫描文件,对源文件进行编码并输出

2,代码分析

1)主函数操作:读取文件

int
main(int argc, char** argv)
{
	char memory = 0;//指示是否操作内存数据
	char compress = 1;//此处表示编码过程,若为0则表示为解码过程
	int opt;
	const char *file_in = NULL, *file_out = NULL;
	FILE *in = stdin;
	FILE *out = stdout;

	/* Get the command line arguments. */
	while((opt = getopt(argc, argv, "i:o:cdhvm")) != -1)//读取命令行参数,此处利用getopt函数读取,最后一个参数是单个字符。
	{
		switch(opt)
		{
		case 'i'://input
			file_in = optarg;
			break;
		case 'o'://output
			file_out = optarg;
			break;
		case 'c'://code
			compress = 1;
			break;
		case 'd'://decode
			compress = 0;
			break;
		case 'h'://输出参数用法的说明
			usage(stdout);
			return 0;
		case 'v'://输出版本号的信息
			version(stdout);
			return 0;
		case 'm'://对内存解码
			memory = 1;
			break;
		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;
		}
	}

	if(memory)//对内存数据进行编解码操作
	{
		return compress ?
			memory_encode_file(in, out) : memory_decode_file(in, out);
	}

	return compress ?
		huffman_encode_file(in, out) : huffman_decode_file(in, out);
}
2)对文件编码:编码函数->huffman_encode_file()

int
huffman_encode_file(FILE *in, FILE *out)
{
	SymbolFrequencies sf;
	SymbolEncoder *se;
	huffman_node *root = NULL;
	int rc;
	unsigned int symbol_count;

	/* Get the frequency of each symbol in the input file. */
	symbol_count = get_symbol_frequencies(&sf, in);//第一遍扫描,统计字节出现的频率(再文件中,符号用字节表示)

	/* Build an optimal table from the symbolCount. */
	se = calculate_huffman_codes(&sf);//建立码树,得到码表
	root = sf[0];//表示根节点为sf[0]

	/* Scan the file again and, using the table
	   previously built, encode it into the output file. */
	rewind(in);//回到文件头,为第二次扫描做准备
	rc = write_code_table(out, se, symbol_count);//再输出文件中写入码表
	if(rc == 0)
		rc = do_file_encode(in, out, se);//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值