哈夫曼编码是最优字长编码吗?

作者&投稿:大米 (若有异议请与网页底部的电邮联系)
哈夫曼编码码长怎么算~

设某信源产生有五种符号u1、u2、u3、u4和u5,对应概率P1=0.4,P2=0.1,P3=P4=0.2,P5=0.1。
霍夫曼编码是变长编码,思路:对概率大的编的码字短,概率小的编的码字长,这样一来所编的总码长就小,这样编码效率就高。上面那样求是不对的,除非你这6个码字是等概率的,各占1/6。应该用对应的概率*其对应得码长,再求和。

实际应用中
除采用定时清洗以消除误差扩散和采用缓冲存储以解决速率匹配以外,主要问题是解决小符号集合的统计匹配,例如黑(1)、白(0)传真信源的统计匹配,采用0和1不同长度游程组成扩大的符号集合信源。游程,指相同码元的长度(如二进码中连续的一串0或一串1的长度或个数)。
按照CCITT标准,需要统计2×1728种游程(长度),这样,实现时的存储量太大。事实上长游程的概率很小,故CCITT还规定:若l表示游程长度,则l=64q+r。

编码唯一性!

哈夫曼编码(Huffman Coding)是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。这种方法是由David.A.Huffman发展起来的。 例如,在英文中,e的出现概率很高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

本文描述在网上能够找到的最简单,最快速的哈夫曼编码。本方法不使用任何扩展动态库,比如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;
这里我用了一个好的诀窍来避免使用任何队列组件。我先前就直到ASCII码只有256个,但我分配了511个(CHuffmanNode nodes[511]),前255个记录ASCII码,而用后255个记录哈夫曼树中的父节点。并且在构造树的时候只使用一个指针数组(ChuffmanNode *pNodes[256])来指向这些节点。同样使用两个变量来操作队列索引(int nParentNode = nNodeCount;nBackNode = nNodeCount –1)。
接着,压缩的最后一步是将每个ASCII编码写入输出缓冲区中:
int nDesIndex = 0;
// loop to write codes
for(nCount = 0; nCount < nSrcLen; nCount++)
{
*(DWORD*)(pDesPtr+(nDesIndex>>3)) |=
nodes[pSrc[nCount]].dwCode << (nDesIndex&7);
nDesIndex += nodes[pSrc[nCount]].nCodeLength;
}
(nDesIndex>>3): >>3 以8位为界限右移后到达右边字节的前面
(nDesIndex&7): &7 得到最高位.
注意:在压缩缓冲区中,我们必须保存哈夫曼树的节点以及位序列,这样我们才能在解压缩时重新构造哈夫曼树(只需保存ASCII值和对应的位序列)。
解压缩
解压缩比构造哈夫曼树要简单的多,将输入缓冲区中的每个编码用对应的ASCII码逐个替换就可以了。只要记住,这里的输入缓冲区是一个包含每个ASCII值的编码的位流。因此,为了用ASCII值替换编码,我们必须用位流搜索哈夫曼树,直到发现一个叶节点,然后将它的ASCII值添加到输出缓冲区中:
int nDesIndex = 0;
DWORD nCode;
while(nDesIndex < nDesLen)
{
nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3)))>>(nSrcIndex&7);
pNode = pRoot;
while(pNode->pLeft)
{
pNode = (nCode&1) ? pNode->pRight : pNode->pLeft;
nCode >>= 1;
nSrcIndex++;
}
pDes[nDesIndex++] = pNode->byAscii;
}

你为啥不说一位编码加上二位编码。。。。

不就是0.45+0.16+2(0.13+0.12+0.09+0.05)=1.39位?


JPEG是矢量图像压缩编码标准?
JPEG使用了1个字节的高4位来表示连续“0”的个数,而使用它的低4位来表示编码下一个非“0”系数所需要的位数,跟在它后面的是量化AC系数的数值。6. 熵编码 使用熵编码还可以对DPCM编码后的直流DC系数和RLE编码后的交流AC系数作进一步的压缩。在JPEG有损压缩算法中,使用霍夫曼编码器来减少熵。使用...

2022年山东大学“832计算机综合”考哪些内容?
3.堆结构应用:堆排序、霍夫曼树、霍夫曼编码 4.左高树基本概念和插入、删除、合并、初始化等操作的实现思想 (十)搜索树 1.二叉搜索树(排序树)基本概念和插入、删除、搜索等操作的实现方法 2.二叉平衡树(AVL树)基本概念和插入、删除、搜索等操作的实现方法 3.m叉搜索树和B-树基本概念以及插入、删除、搜索等操作...

最新的信源编码技术有些啥啊?谁知道给两个名字吧?
(1) 莫尔斯电码 (2) 差值脉冲编码 (3) 预测编码 (4) 运动估算和运动补偿编码 (5) 变换编码 (6) 统计编码 (7) 游程编码和可变字长编码 (8) ASCII码 (9) 哈夫曼编码(Huffman Coding)(10) 算术编码 (11) L-Z编码 ...

下面关于扩展操作码说法,不正确的是。
B.在指令格式中采用扩展码的设计方案是为了保持指令操作的数量不变,而增加指令字长。C.通常在指令字中用一个固定长度的字段来表示基本操作码,而对于一部分不需要的某个地址码的指令,把它们的操作码扩展到该地址字段。D.一个实际可行的优化编码的方法是扩展操作码法,它是介于定长编码和哈夫曼编码之间...

复习资料TLLLSA
3、根据给出的字符串agdfaghdabsb,进行哈夫曼编码。 本回答由提问者推荐 举报| 答案纠错 | 评论 1 0 cn#uQGfGQLGB 采纳率:100% 擅长: 暂未定制 为您推荐: 圆明园毁灭的资料 小学复习资料 复习资料软件 五年级复习资料 两个月的复习资料 初三复习资料 狼复习资料 狼牙山五壮士的资料 其他...

计算机图像处理期末作业,求解答
有这么难吗,dreamwaver 做完,不也有网页的存储地方吗,你把文件用share point designer打开,不行都另存一个,

计算机系统结构试题
设指令字长为12位,每个地址码长为3位。问能否以扩展操作码为其编码?如果其中单地址指令为254条呢?说明其理由。 [分析] 无论是哈夫曼编码,还是扩展操作码编码,其中的短码都不能与长码的首都有相同的。否则,由于短码成了长码的前缀,而指令中除了操作码外,后面所跟的,或者是操作数,或者是操作数所在的寄存器...

noip2009初赛答案
7、最优前缀编码,也称Huffman编码。这种编码组合的特点是对于较频繁使用的元素给与较短的唯一编码,以提高通讯的效率。下面编码组合哪一组不是合法的前缀编码:A)(00,01,10,11)B)(0,1,00,11)C)(0,10,110,111)D)(1,01,000,001)【分析】选择B 0是00的前缀码,这部分是数据结构中哈夫曼编码处的知识。8...

计算机内部用几个字节存放一个7位
在计算机中,一个字节通常由 8 个二进制位组成。而 7 位二进制数在计算机中可以用一个字节的高 7 位来表示,也就是说只需要使用一个字节存放一个 7 位二进制数。因此,计算机内部用 1 个字节存放一个 7 位二进制数。如果要存储多个七位二进制数,则可以使用多个字节来表示。但是如果只需要存储...

哈夫曼编码小数需要扩大倍数吗
需要。哈夫曼编码,又称霍夫曼编码,是一种编码方式,小数是需要扩大倍数。哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法。

西城区15637128928: 什么是变字长最佳编码原理 -
堵堂镇咳: 哈夫曼编码(Huffman Coding),又称霍夫曼编码最佳编码定理:在变字长码中,对于出现概率大的信息符号编以短字长的码;对于出现概率小的信息符号编以长字长的码,如果码字长度严格按照符号概率的大小的相反顺序排列,则平均码字长度一定小于按任何其他符号顺序排列方式得到的码字长度.Huffman编码步骤:概率统计,得到n个不同概率的信号;将n个信源信息符号的n个概率,按概率大小排序;将最后两个小概率相加,概率个数减为n-1;将n-1个概率重新排序;再将最后两个小概率相加,概率个数减为n-2;如此反复n-2次,得到只剩两个概率序列;以二进制码元(0,1)赋值,构成Huffman码字.

西城区15637128928: 哈夫曼编码是什么?、 -
堵堂镇咳: 哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种. Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作...

西城区15637128928: 如何证明哈夫曼编码一定是不重复的最优编码 -
堵堂镇咳: 哈夫曼编码完全依据字符出现概率来构造异字头的平均长度最短的码字,所以频率相同的编码可以互换,两种编码之后的字符串的平均期望长度是相同的.这里你和你同学做出的结果不同是因为哈夫曼树是二叉树,编码频率相同,但插入到二叉树的顺序不同,所以出现了不同的结果.

西城区15637128928: 在什么情况下,等长编码是最优前的编码 -
堵堂镇咳: 在(平均码长为2.24)情况下,等长编码是最优前的编码.常见的等长编码就是前缀码.所谓最优前缀码是指,平均码长或文件总长最小的前缀编码称为最优的前缀码(这里的平均码长相当于码长的期望值). 变长编码可能使解码产生二义性,而前缀码的出现很好地解决了这个问题.而平均码长相当于二叉树的加权路径长度,从这个意义上说,由哈夫曼树生成的编码一定是最优前缀码,故通常不加区分的将哈夫曼编码也称作最优前缀码. 需要注意的是,由于哈夫曼树建立过程的不唯一性可知,生成的哈夫曼编码也是不唯一的.

西城区15637128928: 哈夫曼编码的编码方法怎样?
堵堂镇咳: 哈夫曼编码是一种编码方式,是可变字长编码(VLC)的一种.以哈夫曼树-即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,“...

西城区15637128928: 霍夫曼编码的思想是什么 -
堵堂镇咳: 哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman...

西城区15637128928: 哈夫曼编码实现最优前(最短期望长度)缀码 的源程序 -
堵堂镇咳: 哈夫曼编码为最优前缀码由哈夫曼树求得编码为最优前缀码的原因:① 每个叶子字符ci的码长恰为从根到该叶子的路径长度li,平均码长(或文件总长)又是二叉树的带权路径长度WPL.而哈夫曼树是WPL最小的二叉树,因此编码的平均码长...

西城区15637128928: 哈夫曼编码原理 -
堵堂镇咳: 原发布者:a2420092945 Huffman树及其应用一、最优二叉树(霍夫曼树)预备知识:若干术语路d径:由一结点到另一结点间的分支所构成a→e的路径长度=2beacfg路径长度:路径上的分支数目树长度=10树的路径长度:从树根到每一结点的...

西城区15637128928: 在哈夫曼编码压缩程序中应该如何存储哈夫曼编码? -
堵堂镇咳: 我想你理解错了……你所说的128Bit是编码和解码时用的 树怎么保存,方法很多,最简单的办法是为0x00到0xFF按它们出现的频率保存顺序;因为只有256个元素,所以用1字节就能保存到它们的顺序,例如 0x00 0x05 0x01 0x04 0x02 0xF5 …… …… 要保存这种表示方式也只是要512字节而已;重建树的时候重再根据这些数据来把树创建出来就是了;最后建议你把哈夫曼编码原理重新再看一次,是看“原理”

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网