Huffman编解码

Huffman编解码算法实现与压缩效率分析

一.背景知识及相关公式

1.信源熵

信源熵是信息的度量单位,一般用H表示,单位是比特,对于任意一个随机变量,它的熵定义为 ,变量的不确定性越大,熵也就越大。


2.Huffman编码

(1)Huffman编码是一种无失真编码的编码方式,可变长编码的一种;
(2)Huffman编码基于信源的概率统计模型,它的基本思路是,出现概率小的信源符号编长码,出现概率大的信源符号编短码,从而使平均码长最小。
(3)在程序实现中常使用一种叫做树的数据结构实现Huffman编码,由它编出的码是即时码。

3.Huffman编码算法

(1)将文件以ASCII字符流的形式读入,统计每个符号的发生频率;
(2)将所有文件中出现过的字符按照频率从小到大的顺序排列 ;
(3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们根节点,这两个叶子节点不再参与比较,新的根节点参与比较;
(4)重复 3,直到最后得和为1的根节点;
(5)将形成的二叉树左节点标0,右节点标1,把从最上面的根节点到最下面叶子点途中遇到的0、1序列串起来,得到了各个字符的编码表示。

二.实验过程

1.数据结构

(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;/*该节点左右孩子的指针*/
		};
		unsigned char symbol;/*信源符号,一个字节的二进制数值*/
	};
} huffman_node;

(2) Huffman码字节点
typedef struct huffman_code_tag
{
	unsigned long numbits;/*码字长度 */
	/*码字的第1位存于bits[0]的第1位,
	码字的第2位存于bits[0]的第2位,
	码字的第8位存于bits[0]的第8位,
	码字的第9位存于bits[1]的第1位,*/
	unsigned char *bits;
} huffman_code;

2.Huffman编码

(1)编码流程
 
(2)读入源文件

int main(int argc, char** argv)
{
	char memory = 0;
	char compress = 1;
	int opt;
	const char *file_in = NULL, *file_out = NULL;
	const char *file_out_table = NULL;
	FILE *in = stdin;
	FILE *out = stdout;
	FILE * outTable = NULL;
	/*获取命令行参数*/
	while((opt = getopt(argc, argv, "i:o:cdhvmt:")) != -1) 
	{
		switch(opt)
		{
		case 'i'://输入文件
			file_in = optarg;
			break;
		case 'o'://输出文件
			file_out = optarg;
			break;
		case 'c'://编码
			compress = 1;
			break;
		case 'd'://解码
			compress = 0;
			break;
		case 'h'://参数用法输出到屏幕
			usage(stdout);
			return 0;
		case 'v'://版本信息输出到屏幕
			version(stdout);
			return 0;
		case 'm':
			memory = 1;//对内存数据进行编码
			break;
		case 't'://编码结果输出
			file_out_table = optarg;			
			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));//strerror函数返回指向错误原因字符串的指针,errno是错误代码,errno.h中包含很多错误定义
			return 1;
		}
	}
	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;
		}
	}
	if(memory)//memeory=1对内存数据进行编码,反之解码
	{
		return comp
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值