云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > 用C++实现Huffman文件编码和解码

用C++实现Huffman文件编码和解码

  • 62 次阅读
  • 3 次下载
  • 2025/5/7 4:54:55

这个是代码是昨天写完的,一开始的时候还出了点小bug,这个bug在晚上去吃饭的路上想明白的,回来更改之后运行立刻完成最后一步,大获成功。 简单说下huffman编码和文件压缩主要的技术。

Huffman编码,解码:

I 创建Huffman树

II 根据Huffman树实现编码,并将编码结果和要编码的数据建立映射关系。

III Huffman解码,也就是根据获取的Huffman码来逆向获取解码信息,而且你从解压文件中一次性获取的数据是一个很长的字符串,没有预处理好的成段字符串式Huffman码。1

I 首先,如何创建Huffman树?

在这个我在前天的那篇文章中简单的提了一下,现在好好说一下。如果你不知道什么是Huffman树,请google之~

对于获取到的文件,首先要做的就是,建立一个长度为256的int数组,全部置零,然后以字节流的形式读取文件,并对字节流中的字节出现次数进行统计,方法就是以字节数值为数组偏移地址,对应的数组元素进行+1操作。另外这里需要提一下的就是,用于存储文件字节流的缓冲区最好是unsigned char类型,因为这样能直接使用,如果是char的,在转化为int类型的时候,一旦数值大于127,因为补码问题,你就直接乘上了通往未知数值的高铁~

完成统计之后,将这个数组中出现次数不为0的元素添加对应大小的二叉树节点数组中,然后以出现次数为Key值,进行排序。

在排序完成之后,就能开始构建Huffman树了。操作如下:

1 如果数组中元素个数不为1,将前两个元素构造为一个临时节点的子树,此时临时节点的Key值为两个元素Key值之和,然后删除数组中的第一个元素(从数组中删除),再将临时节点赋值给当前数组的第一个元素。

(其实就是将前两个元素添加到一个临时节点的左右根节点,然后在原数组中删除这两个元素,http://mz.qqtop1.com,接着再将这个临时节点插入到数组头部,充当新的节点。上面的那段描述我觉得说的不是很清楚,但是那个是我在代码中发现的一个可以优化的地方,减少了一个元素的删除操作)

2 此时数组依据key值的排序很有可能已经不再有序,而又因为仅有一个乱序元素,所以专门设计了一个函数,一次完成排序,效率,应该是最高的了。重复1

这样当数组中只有1个元素的时候,就是Huffman树的根节点了。

这样,Huffman树的构造就完成了。我上面说的可能不是很清楚,你看了之后可能会有疑问,所以我在这贴下部分代码,你可以看一下,就是这么简单,而且很巧妙。

Huffman树节点,一开始就是一个Struct,但是因为涉及到了STL,所以添加了方法

1 struct HaffmanStruct 2 {

3 //a small structure

4 HaffmanStruct():val(0),ncounts(0),lNext(NULL),rNext(NULL){} 5 bool operator < (HaffmanStruct &); 6 bool operator > (HaffmanStruct &); 7 void Reset();

8 unsigned char val; 9 unsigned int ncounts; 10 char HuffmanCode[254]; 11 //used for tree

12 HaffmanStruct * lNext; 13 HaffmanStruct * rNext; 14 };

给他一个数组,他给你一颗Huffman树

1 void HuffManEncode(vector & vecValidNumberArray) 2 {

3 HaffmanStruct ValidStruct;//temporary struct 4 //Analysis

5 while(vecValidNumberArray.size() != 1) 6 {

7 ValidStruct.Reset();

8 ValidStruct.ncounts = vecValidNumberArray[0].ncounts + vecValidNumberArray[1].ncounts;

9 ValidStruct.lNext = new HaffmanStruct;

10 *ValidStruct.lNext = vecValidNumberArray[0]; 11 ValidStruct.rNext = new HaffmanStruct;

12 *ValidStruct.rNext = vecValidNumberArray[1];

13 vecValidNumberArray.erase(vecValidNumberArray.begin()); 14 vecValidNumberArray[0] = ValidStruct;

15 SingleSort(&vecValidNumberArray[0], vecValidNumberArray.size(), 0);

16 } 17 }

以上就是Huffman树构造的全部过程。

http://www.78name.com

II 根据Huffman树获取Huffman编码

对树最有效的访问方式就是遍历,而遍历有两种方式:深度优先遍历和广度优先遍历。不过学过Huffman编码的人都知道,Huffman的编码,必须使用深度优先遍历,你懂得~

我在此默认的模式是,左树为0,右树为1.而这个遍历函数需要使用一个编码缓冲区和输出目标,以及深度探测。于是乎,一个参数好多的递归函数新鲜出炉了,昨天才被我正式造出来。

1 template

2 void ErgodicTree(T & Root, char * szStr, int nDeep, string pStrArray[]) 3 {

4 if(Root.lNext == NULL && Root.rNext == NULL) 5 pStrArray[Root.val] = szStr; 6 szStr[nDeep] = '0';

7 if(Root.lNext != NULL)

8 ErgodicTree(*Root.lNext, szStr, nDeep + 1, pStrArray); 9 szStr[nDeep] = '1';

10 if(Root.rNext != NULL)

11 ErgodicTree(*Root.rNext, szStr, nDeep + 1, pStrArray); 12 szStr[nDeep] = 0; 13 }

需要注意的是,编码和解码的递归函数是不一样的,在这专门提一下,因为编码是一次性遍历完成全部的节点,而解码是每次只遍历到叶子节点。

可以看到,每次向下传递参数的时候,左树就置'0',右树就置'1',返回的时候必须清零。这样下一级函数会获取的结果,并且根据Deep的值对应置位,上级函数函数的乞讨递归也不会受到影响。代码写的很简单,但是其实很细致。 一旦访问到了叶子节点,就直接输出,这里写的也很巧妙,也就是在这里,获取到了Huffman编码,输出到对应的string数组中。 这样,就完成了Huffman编码。 III Huffman解码

用Huffman解码之前,你获取到的是一个很长的,内容是'0'和'1'的字符串。在我的代码中,这个字符串的长度是1024.

其实Huffman的解码实现起来也很简单,但是,存在细节性问题。

比如:从递归函数中获取返回值、下次解码的偏移地址、字符串访问已经到头了,但是解码失败(你想想这个问题出现的圆心),此时字符串中还剩下几个未解码的字符。

搜索更多关于: 用C++实现Huffman文件编码和解码 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

这个是代码是昨天写完的,一开始的时候还出了点小bug,这个bug在晚上去吃饭的路上想明白的,回来更改之后运行立刻完成最后一步,大获成功。 简单说下huffman编码和文件压缩主要的技术。 Huffman编码,解码: I 创建Huffman树 II 根据Huffman树实现编码,并将编码结果和要编码的数据建立映射关系。 III Huffman解码,也就是根据获取的Huffman码来逆向获取解码信息,而且你从解压文件中一次性获取的数据是一个很长的字符串,没有预处理好的成段字符串式Huffman码。1 I 首先,如何创建Huffman树? 在这个我在前天的那篇文章中简单的提了一下,现在好好说一下。如果你不知道什么是Huffman树,请google之~ 对于获取到的文件,首先要做的就是,建立一个

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com