Welcome

首页 / 软件开发 / C++ / 简单快速的哈夫曼编码

简单快速的哈夫曼编码2010-12-22 vckbase Hatem Mostafa介绍

本文描述在网上能够找到的最简单,最快速的哈夫曼编码。本方 法不使用任何扩展动态库,比如STL或者组件。只使用简单的C函数,比如: memset,memmove,qsort,malloc,realloc和memcpy。

因此,大家都会发现 ,理解甚至修改这个编码都是很容易的。

背景

哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。哈夫 曼压缩属于可变代码长度算法一族。意思是个体符号(例如,文本文件中的字符 )用一个特定长度的位序列替代。因此,在文件中出现频率高的符号,使用短的 位序列,而那些很少出现的符号,则用较长的位序列。

编码使用

我用简单的C函数写这个编码是为了让它在任何地方使用都会比较方便。你可以 将他们放到类中,或者直接使用这个函数。并且我使用了简单的格式,仅仅输入 输出缓冲区,而不象其它文章中那样,输入输出文件。

bool CompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);
bool DecompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);
要点说明

速度

为了让 它(huffman.cpp)快速运行,我花了很长时间。同时,我没有使用任何动态库, 比如STL或者MFC。它压缩1M数据少于100ms(P3处理器,主频1G)。

压缩

压缩代码非常简单,首先用ASCII值初始化511个哈夫曼节点:

CHuffmanNode nodes[511];
for(int nCount = 0; nCount < 256; nCount++)
nodes[nCount].byAscii = nCount;
然 后,计算在输入缓冲区数据中,每个ASCII码出现的频率:for(nCount = 0; nCount < nSrcLen; nCount++)
nodes[pSrc [nCount]].nFrequency++;
然后,根据频率进行排序:qsort (nodes, 256, sizeof(CHuffmanNode), frequencyCompare);现在,构造 哈夫曼树,获取每个ASCII码对应的位序列:int nNodeCount = GetHuffmanTree(nodes);构造哈夫曼树非常简单,将所有的节点放到一 个队列中,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点 的频率之和。这样,新节点就是两个被替换节点的父节点了。如此循环,直到队 列中只剩一个节点(树根)。// parent node
pNode = &nodes[nParentNode++];
// pop first child
pNode- >pLeft = PopNode(pNodes, nBackNode--, false);
// pop second child
pNode->pRight = PopNode(pNodes, nBackNode--, true);
// adjust parent of the two poped nodes
pNode->pLeft- >pParent = pNode->pRight->pParent = pNode;
// adjust parent frequency
pNode->nFrequency = pNode->pLeft- >nFrequency + pNode->pRight->nFrequency;