霍夫曼编码原理
霍夫曼编码原理(一)
![霍夫曼编码原理(一)](https://img.taocdn.com/s3/m/2be2cd92d0f34693daef5ef7ba0d4a7302766c15.png)
霍夫曼编码原理(一)霍夫曼编码–信息压缩的艺术介绍•什么是霍夫曼编码?•为什么需要进行信息压缩?霍夫曼树•霍夫曼树的定义•构建霍夫曼树的步骤•霍夫曼树的特点霍夫曼编码的原理•比特位的表示•无冗余编码•可译性和前缀性•前缀码的最优性构建霍夫曼编码表•统计字符频率•构建霍夫曼树•生成霍夫曼编码表霍夫曼编码的应用•文本文件压缩•图像文件压缩总结•霍夫曼编码的优点•霍夫曼编码的局限性•霍夫曼编码的未来发展霍夫曼编码是一种常用的信息压缩技术,通过构建霍夫曼树和编码表,将原始数据转化为二进制码,从而实现对信息的高效压缩。
在构建霍夫曼树的过程中,每个数据被看作一个节点,根据频率构建一个树形结构。
构建霍夫曼树的步骤包括:选择频率最低的两个节点,合并为一个新节点,然后将该新节点放回原来的节点集合中,并按照频率进行排序,重复该过程直到只剩下一个节点为止。
霍夫曼树的特点是,频率越高的节点越靠近根节点,频率越低的节点越接近树的边缘。
霍夫曼编码的原理是基于比特位的表示和无冗余编码。
通过对每个字符进行编码,将字符映射为对应的二进制码。
此外,霍夫曼编码还满足可译性和前缀性的要求,即每个编码都是不会引起歧义的,且任意一个编码都不是另一个编码的前缀。
构建霍夫曼编码表的过程包括统计字符的频率、构建霍夫曼树和生成霍夫曼编码表。
通过统计字符频率,我们可以得到每个字符在文本中出现的次数。
然后,根据字符频率构建霍夫曼树,将频率较低的字符放在树的边缘,频率较高的字符放在根节点附近。
最后,通过霍夫曼树,我们可以生成霍夫曼编码表,将每个字符对应的霍夫曼编码存储起来。
霍夫曼编码广泛应用于文本文件和图像文件的压缩中。
在文本文件压缩过程中,通过对文本中的字符进行编码,可以有效地减少文件的大小。
在图像文件压缩过程中,霍夫曼编码可用于对图像的像素值进行编码,以实现对图像文件的压缩。
综上所述,霍夫曼编码是一种高效的信息压缩技术,具有无冗余、可译性和前缀性的特点。
Huffman霍夫曼编码
![Huffman霍夫曼编码](https://img.taocdn.com/s3/m/c889c8ca6137ee06eff91897.png)
霍夫曼编码的局限性
利用霍夫曼编码,每个符号的编码长度只能 为整数,所以如果源符号集的概率分布不是 2负n次方的形式,则无法达到熵极限。 输入符号数受限于可实现的码表尺寸 译码复杂 需要实现知道输入符号集的概率分布 没有错误保护功能
尾码为DIFF的B位
原码,若DIFF0 反码,若DIFF0
按此规则,当DIFF0时,尾码的最高位是“1”; 而当DIFF0时则为“0”。解码时则可借此来判断 DIFF的正负。 书中例4—9
自适应霍夫曼编码提出的目的和意义:
在静态霍夫曼编码中,要构造编码树必须提前统计 被编码对象中的符号出现概率,因此必须对输入符 号流进行两遍扫描,第一遍统计符号出现概率并构 造编码树,第二遍进行编码,这在很多实际应用的 场合中之不能接受的。其次,在存储和传送霍夫曼
i 1 i
n
单位:以2为底的对数时是比特/符号(bit/symbol); 以e为底的对数时是奈特/符号(nat/symbol); 以10为底的对数时是哈特/符号( hart/symbol) 其中 I(xi)=-logp(xi) 表示某个事件xi的信息量。
平均码长 编码效率
例:现有一个由5个不同符号组成的30个符号的字 符串:BABACACADADABBCBABEBEDDABEEEBB 计算 (1) 该字符串的霍夫曼码 (2) 该字符串的熵 (3) 该字符串的平均码长
霍夫曼(Huffman)编码是一种统计编码。 属于无损(lossless)压缩编码。 以霍夫曼树─即最优二叉树,带权路径长 度最小的二叉树,经常应用于数据压缩。 根据给定数据集中各元素所出现的频率来 压缩数据的一种统计压缩编码方法。这些 元素(如字母)出现的次数越多,其编码的 位数就越少。 广泛用在JPEG, MPEG, H.2X等各种信息编 码标准中。
Huffman编码原理简介
![Huffman编码原理简介](https://img.taocdn.com/s3/m/cfc66b631ed9ad51f01df2f3.png)
以下是Huffman编码原理简介:霍夫曼(Huffman)编码是1952年为文本文件而建立,是一种统计编码。
属于无损压缩编码。
霍夫曼编码的码长是变化的,对于出现频率高的信息,编码的长度较短;而对于出现频率低的信息,编码长度较长。
这样,处理全部信息的总码长一定小于实际信息的符号长度。
对于学多媒体的同学来说,需要知道Huffman编码过程的几个步骤:l)将信号源的符号按照出现概率递减的顺序排列。
(注意,一定要递减)2)将最下面的两个最小出现概率进行合并相加,得到的结果作为新符号的出现概率。
3)重复进行步骤1和2直到概率相加的结果等于1为止。
4)在合并运算时,概率大的符号用编码0表示,概率小的符号用编码1表示。
5)记录下概率为1处到当前信号源符号之间的0,l序列,从而得到每个符号的编码。
下面我举个简单例子:一串信号源S={s1,s2,s3,s4,s5}对应概率为p={40,30,15,10,5},(百分率)按照递减的格式排列概率后,根据第二步,会得到一个新的概率列表,依然按照递减排列,注意:如果遇到相同概率,合并后的概率放在下面!最后概率最大的编码为0,最小的编码为1。
如图所示:所以,编码结果为s1=1s2=00s3=010s4=0110s5=0111霍夫曼编码具有如下特点:1) 编出来的码都是异字头码,保证了码的唯一可译性。
2) 由于编码长度可变。
因此译码时间较长,使得霍夫曼编码的压缩与还原相当费时。
3) 编码长度不统一,硬件实现有难度。
4) 对不同信号源的编码效率不同,当信号源的符号概率为2的负幂次方时,达到100%的编码效率;若信号源符号的概率相等,则编码效率最低。
5) 由于0与1的指定是任意的,故由上述过程编出的最佳码不是唯一的,但其平均码长是一样的,故不影响编码效率与数据压缩性能。
霍夫曼编码的C语言实现#include <stdio.h>#include <malloc.h>#include <conio.h>#include <string.h>#include <stdlib.h>#define HuffmanTree HF#define HuffmanCode HMCtypedef struct{unsigned int weight;unsigned int parent,lchild,rchild;} HTNode,*HF;typedef char **HMC;typedef struct {unsigned int s1;unsigned int s2;} MinCode;void Error(char *message);HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n); MinCode Select(HF HT,unsigned int n);void Error(char *message){fprintf(stderr,"Error:%s\n",message);exit(1);}HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n) {unsigned int i,s1=0,s2=0;HF p;char *cd;unsigned int f,c,start,m;MinCode min;if(n<=1) Error("Code too small!");m=2*n-1;HT=(HF)malloc((m+1)*sizeof(HTNode));for(p=HT,i=0;i<=n;i++,p++,w++){p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;}for(;i<=m;i++,p++){p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}for(i=n+1;i<=m;i++){min=Select(HT,i-1);s1=min.s1;s2=min.s2;HT[s1].parent=i;HT[s2].parent=i;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;}printf("HT List:\n");printf("Number\t\tweight\t\tparent\t\tlchild\t\trchild\n"); for(i=1;i<=m;i++)printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild); HC=(HMC)malloc((n+1)*sizeof(char *));cd=(char *)malloc(n*sizeof(char *));cd[n-1]='\0';for(i=1;i<=n;i++){start=n-1;for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)if(HT[f].lchild==c) cd[--start]='0';else cd[--start]='1';HC[i]=(char *)malloc((n-start)*sizeof(char *));strcpy(HC[i],&cd[start]);}free(cd);return HC;}void main(){MinCode Select(HF HT,unsigned int n);HF HT=NULL;HuffmanCode HC=NULL;unsigned int *w=NULL;printf("请输入节点数n:");scanf("%d",&n);w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *)); w[0]=0;printf("请输入权重:\n");for(i=1;i<=n;i++){printf("w[%d]=",i);scanf("%d",&w[i]);}HC=HuffmanCoding(HT,HC,w,n);printf("HMC:\n");printf("Number\t\tWeight\t\tCode\n");for(i=1;i<=n;i++)printf("%d\t\t%d\t\t%s\n",i,w[i],HC[i]);}MinCode Select(HF HT,unsigned int n){unsigned int min,secmin;unsigned int temp;unsigned int i,s1,s2,tempi;MinCode code;s1=1;s2=1;for(i=1;i<=n;i++)if(HT[i].parent==0){min=HT[i].weight;s1=i;break;}tempi=i++;for(;i<=n;i++)if(HT[i].weight<min&&HT[i].parent==0){min=HT[i].weight;s1=i;}for(i=tempi;i<=n;i++)if(HT[i].parent==0&&i!=s1){secmin=HT[i].weight;s2=i;break;}for(i=1;i<=n;i++)if(HT[i].weight<secmin&&i!=s1&&HT[i].parent==0) {secmin=HT[i].weight;s2=i;}if(s1>s2){temp=s1;s1=s2;s2=temp;}code.s1=s1;code.s2=s2;return code;}。
霍夫曼编码压缩率
![霍夫曼编码压缩率](https://img.taocdn.com/s3/m/f840a5484b7302768e9951e79b89680203d86bad.png)
霍夫曼编码压缩率霍夫曼编码压缩率:原理、计算方法与应用引言:在当今信息爆炸的时代,数据的传输和存储已经成为了我们生活中不可或缺的一部分。
然而,随着大数据和互联网的快速发展,数据量的增加也带来了挑战,因为大量的数据会占据大量的存储空间和带宽资源。
因此,如何在节省存储空间和减少数据传输时间的基础上保证数据的完整性和准确性成为了一个新的问题。
其中一种解决方案就是使用压缩算法来减小数据的大小。
本文将重点讨论一种常用的压缩算法——霍夫曼编码算法,以及如何计算霍夫曼编码的压缩率。
一、霍夫曼编码的原理霍夫曼编码是由霍夫曼(David A. Huffman)于1952年提出的一种可变字长编码方法,它是一种前缀编码技术。
它的思想非常简单,即为每个待编码的符号(通常是字符)分配一个唯一的二进制码字,使得位数较多的码字分配给出现频率较低的符号,位数较少的码字分配给出现频率较高的符号。
这样做的好处是可以通过调整不同符号的编码长度来最大限度地减少编码后的文件大小。
二、如何计算霍夫曼编码的压缩率下面将介绍计算霍夫曼编码的压缩率的方法:1. 统计字符频率:首先需要对待压缩的数据进行字符频率的统计。
字符频率是指在待压缩的数据中每个字符出现的次数。
可以通过扫描整个待压缩的数据,统计每个字符出现的次数来得到字符频率表。
2. 构建霍夫曼树:根据字符频率表,可以构建一棵霍夫曼树。
霍夫曼树的构建过程是将字符按照频率从小到大进行排序,然后每次选取频率最小的两个字符节点,将它们合并成一个新的节点,该新节点的频率是选取的两个节点的频率之和。
重复这个过程,直到所有的字符节点都被合并成一个根节点为止。
3. 霍夫曼编码:通过遍历霍夫曼树,可以得到每个字符对应的霍夫曼编码。
在遍历过程中,左侧路径记为0,右侧路径记为1。
当遍历到叶子节点时,即可得到该字符对应的霍夫曼编码。
将每个字符及其对应的霍夫曼编码存储在编码表中。
4. 计算压缩率:在进行霍夫曼编码后,可以计算原始数据和编码后的数据的大小。
霍夫曼编码原理
![霍夫曼编码原理](https://img.taocdn.com/s3/m/96a7026976232f60ddccda38376baf1ffd4fe356.png)
霍夫曼编码是一种变长编码方式,用于将字符或符号序列转换为二进制数,以便用于数据压缩或传输。
霍夫曼编码的原理如下:
统计每个字符或符号在待编码序列中出现的频率,并根据频率构建一个频率表。
根据频率表,构建一个霍夫曼树。
霍夫曼树是一种特殊的二叉树,其中每个叶子节点代表一个字符或符号,并且每个内部节点的权值等于其左右子节点权值之和。
从根节点开始,为每个叶子节点赋予一个编码。
左子节点的编码为0,右子节点的编码为1。
通过遍历霍夫曼树,可以得到每个字符或符号的霍夫曼编码。
将原始序列中的每个字符或符号替换为对应的霍夫曼编码,得到压缩后的二进制数。
霍夫曼编码的特点是:
每个字符或符号的编码都是唯一的,不会出现编码冲突。
出现频率高的字符或符号的编码较短,而出现频率低的字符或符号的编码较长,从而实现了数据的压缩。
霍夫曼编码是一种前缀编码,即任何一个字符或符号的编码都不是另一个字符或符号编码的前缀,这样可以避免解码时的歧义。
在实际应用中,霍夫曼编码广泛用于数据压缩、图像压缩和音频压缩等领域,能够有效减小数据的存储空间和传输带宽。
霍夫曼编码编码效率
![霍夫曼编码编码效率](https://img.taocdn.com/s3/m/bd744c18abea998fcc22bcd126fff705cc175cb3.png)
霍夫曼编码编码效率1. 引言霍夫曼编码是一种用于数据压缩的算法,通过将出现频率高的字符用较短的编码表示,而将出现频率低的字符用较长的编码表示,从而达到减小数据存储空间的目的。
本文将探讨霍夫曼编码在编码效率方面的优势和应用。
2. 霍夫曼编码原理霍夫曼编码是一种无损压缩算法,主要基于以下两个原理: - 高频字符使用较短的二进制位表示,低频字符使用较长的二进制位表示。
- 编码之间不会发生冲突,即任何一个字符的编码都不会是另一个字符编码的前缀。
3. 编码效率分析3.1 平均比特数霍夫曼编码通过将高频字符用较短的二进制位表示,可以有效地减小数据存储空间。
平均比特数是衡量编码效率的指标之一,它表示每个字符平均需要多少比特来进行表示。
举例来说,如果有一个包含10个不同字符的文本文件,并且每个字符在文件中出现的次数如下表所示:字符出现次数A 100B 200C 300D 400E 500F 600G 700H 800I 900J 1000使用霍夫曼编码对每个字符进行编码,可以得到如下结果:A: 000B: 001C: 010D: 011E: 10F: 110G: 1110H: 1111I: 10000J: 10001根据上述编码方案计算平均比特数为:(100 * 3 + 200 *3 +300 *3 +400 *3 +500 *2 +600 *3 +700 *4 +800 *4 +900 *5 +100 0 *5) / (100+200+300+400+500+600+700+800+900+1000) = (48000 / 5500) ≈8.73比特/字符。
可以看出,霍夫曼编码相较于其他编码方式具有更高的编码效率。
3.2 压缩比率压缩比率是衡量数据压缩效果的指标之一,它表示压缩后的数据大小与原始数据大小之间的比值。
霍夫曼编码的压缩比率通常比较高,尤其是对于含有大量重复字符的数据。
使用上一节中的例子,假设原始数据大小为10KB,经过霍夫曼编码后,可以得到的压缩后的数据大小为8.73比特/字符 * 5500字符≈ 4782.5比特。
霍夫曼编码的平均码长公式
![霍夫曼编码的平均码长公式](https://img.taocdn.com/s3/m/c108ef16366baf1ffc4ffe4733687e21af45ffa3.png)
霍夫曼编码的平均码长公式霍夫曼编码是一种基于贪心策略的编码方式,它可以将字符或符号集合转换为最优编码,从而实现数据压缩的目的。
而霍夫曼编码的平均码长公式则是用来计算霍夫曼编码的平均码长的公式,它在数据压缩领域中有着广泛的应用。
一、霍夫曼编码的基本原理霍夫曼编码是一种可变长度编码,它是基于字符出现频率的统计信息来构建编码表的。
具体而言,霍夫曼编码的基本原理可以归纳为以下几个步骤:1. 统计字符出现频率:对于给定的一段文本,首先需要统计每个字符出现的频率,即每个字符在文本中出现的次数。
2. 构建霍夫曼树:根据字符出现频率,构建一棵霍夫曼树,其中频率较小的字符位于树的底层,频率较大的字符位于树的顶层。
3. 生成编码表:从霍夫曼树的根节点开始,向下遍历树的每个节点,对于左子树的节点,将编码值设为0,对于右子树的节点,将编码值设为1,直到遍历到每个叶子节点为止,生成每个字符的霍夫曼编码。
4. 进行数据压缩:将文本中的每个字符替换为其对应的霍夫曼编码,从而实现数据压缩的目的。
二、霍夫曼编码的平均码长公式霍夫曼编码的平均码长公式是用来计算霍夫曼编码的平均码长的公式,它的具体形式为:L = ∑ (fi * li)其中,L表示霍夫曼编码的平均码长,fi表示第i个字符出现的频率,li表示第i个字符的霍夫曼编码长度。
在这个公式中,频率越高的字符,其霍夫曼编码长度越短,而频率越低的字符,其霍夫曼编码长度越长。
因此,霍夫曼编码的平均码长可以作为衡量编码效率的指标,其值越小,表示编码效率越高。
三、霍夫曼编码的应用霍夫曼编码在数据压缩领域中有着广泛的应用。
在实际的数据传输和存储中,数据的大小往往是一个重要的限制因素。
而通过使用霍夫曼编码,可以将数据进行有效压缩,从而减少数据传输和存储所需的空间和时间。
此外,霍夫曼编码还被广泛应用于图像、音频和视频等多媒体数据的压缩中。
通过将多媒体数据转换为二进制数据,并采用霍夫曼编码进行压缩,可以大幅度减少多媒体数据的存储和传输所需的空间和带宽。
霍夫曼编码原理及编码规则
![霍夫曼编码原理及编码规则](https://img.taocdn.com/s3/m/70ac3941eef9aef8941ea76e58fafab069dc44b3.png)
霍夫曼编码原理及编码规则引言概述:霍夫曼编码是一种常用的数据压缩算法,通过将出现频率较高的字符用较短的编码表示,从而实现对数据的高效压缩。
本文将介绍霍夫曼编码的原理及编码规则,并分析其在数据压缩中的应用。
正文内容:1. 霍夫曼编码原理1.1 可变长度编码- 霍夫曼编码是一种可变长度编码,不同字符的编码长度不同。
- 出现频率较高的字符使用较短的编码,出现频率较低的字符使用较长的编码。
1.2 无前缀编码- 霍夫曼编码是一种无前缀编码,即任何一个字符的编码都不是其他字符编码的前缀。
- 这样可以避免解码时的歧义,保证解码的唯一性。
1.3 最优编码- 霍夫曼编码是一种最优编码,即平均编码长度最短。
- 通过构建霍夫曼树,将出现频率较高的字符放在树的顶部,出现频率较低的字符放在树的底部,从而实现最优编码。
2. 霍夫曼编码规则2.1 构建霍夫曼树- 统计字符出现的频率,根据频率构建霍夫曼树。
- 霍夫曼树的构建可以使用贪心算法,每次选择频率最低的两个节点合并,直到只剩下一个根节点。
2.2 分配编码- 从根节点开始,向左走为0,向右走为1,将每个字符的编码从根节点到叶子节点的路径记录下来。
- 通过遍历霍夫曼树,分配每个字符的编码。
2.3 压缩数据- 将原始数据中的每个字符替换为对应的编码。
- 将编码后的数据按照固定长度进行存储,从而实现数据的压缩。
3. 应用场景3.1 数据压缩- 霍夫曼编码可以对数据进行高效压缩,减小存储空间的占用。
- 在图像、音频、视频等大数据文件的传输和存储中,霍夫曼编码被广泛应用。
3.2 传输错误检测- 霍夫曼编码具有一定的纠错能力,可以检测传输中的错误。
- 通过校验编码的长度和校验和等方式,可以检测出传输中发生的错误。
3.3 数据加密- 霍夫曼编码可以用于数据加密,通过将原始数据转换为编码后的数据,增加数据的安全性。
- 在信息安全领域中,霍夫曼编码被用于数据加密和解密的过程。
总结:霍夫曼编码是一种可变长度、无前缀的最优编码算法,通过构建霍夫曼树和分配编码,实现对数据的高效压缩。
霍夫曼编码原理
![霍夫曼编码原理](https://img.taocdn.com/s3/m/3b9fe265f5335a8102d220b1.png)
霍夫曼编码四川大学计算机学院2009级戚辅光【关键字】霍夫曼编码原理霍夫曼译码原理霍夫曼树霍夫曼编码源代码霍夫曼编码分析霍夫曼编码的优化霍夫曼编码的应用【摘要】哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。
uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman 编码。
哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。
它属于可变代码长度算法一族。
意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。
因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
【正文】引言哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。
uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
霍夫曼编码原理:霍夫曼编码的基本思想:输入一个待编码的串,首先统计串中各字符出现的次数,称之为频次,假设统计频次的数组为count[],则霍夫曼编码每次找出count数组中的值最小的两个分别作为左右孩子,建立他们的父节点,循环这个操作2*n-1-n(n是不同的字符数)次,这样就把霍夫曼树建好了。
建树的过程需要注意,首先把count数组里面的n个值初始化为霍夫曼树的n个叶子节点,他们的孩子节点的标号初始化为-1,父节点初始化为他本身的标号。
接下来是编码,每次从霍夫曼树的叶子节点出发,依次向上找,假设当前的节点标号是i,那么他的父节点必然是myHuffmantree[i].parent,如果i是myHuffmantree[i].parent 的左节点,则该节点的路径为0,如果是右节点,则该节点的路径为1。
matlab霍夫曼编码及译码原理
![matlab霍夫曼编码及译码原理](https://img.taocdn.com/s3/m/8e1f9fb7ed3a87c24028915f804d2b160b4e8614.png)
matlab霍夫曼编码及译码原理霍夫曼编码是一种无损数据压缩算法,它通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而达到压缩数据的目的。
霍夫曼编码的核心思想是利用字符出现的频率来构建一棵树,使得出现频率高的字符在树的顶部,而出现频率低的字符在树的底部,然后对每个字符进行编码,使得编码的长度与字符出现的频率成反比。
一、霍夫曼编码的原理1. 构建霍夫曼树首先,需要统计每个字符在待压缩数据中出现的频率,然后将这些字符和它们的频率构建成一棵树。
构建霍夫曼树的过程可以采用贪心算法,即每次从频率最小的两个节点开始合并,直到所有节点都合并成一棵树。
2. 给每个字符分配编码在霍夫曼树构建完成后,需要对每个字符进行编码。
编码的规则是:从根节点开始,向左走为0,向右走为1,直到到达叶子节点,将走过的路径上的0和1分别记录下来,这就是该字符的霍夫曼编码。
3. 压缩数据将待压缩数据中的每个字符用它的霍夫曼编码替代,从而得到压缩后的数据。
由于霍夫曼编码的长度与字符出现的频率成反比,因此出现频率较高的字符用较短的编码表示,从而达到了压缩数据的目的。
二、霍夫曼译码的原理1. 构建霍夫曼树在进行霍夫曼译码之前,需要先构建一棵与编码时使用的霍夫曼树相同的树。
2. 译码将压缩后的数据中的每个编码按照编码时的规则进行解码,即从根节点开始,按照编码中的0和1向左或向右走,直到到达叶子节点,这个叶子节点所代表的字符就是该编码所表示的字符。
3. 还原数据将解码后的字符按照原来的顺序组合起来,就得到了压缩前的数据。
总之,霍夫曼编码及译码是一种常用的无损数据压缩算法,其核心思想是利用字符出现的频率来构建一棵树,从而达到压缩数据的目的。
huffman编码的原理
![huffman编码的原理](https://img.taocdn.com/s3/m/084376fb1b37f111f18583d049649b6648d70920.png)
huffman编码的原理
Huffman编码是一种基于哈夫曼树的数据压缩算法,它利用字符出现的频率来构建一种高效的编码方案,使得出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示。
Huffman编码的原理如下:
1. 统计字符出现的频率:遍历需要编码的数据,统计每个字符出现的频率。
2. 构建哈夫曼树:根据字符的频率,构建一颗哈夫曼树。
频率越高的字符在树中的位置越靠近根节点。
3. 分配编码:从根节点开始,向左走为0,向右走为1,分配每个字符的编码。
在树中,到达一个字符节点时,路径上的0和1的组合就是该字符的编码。
4. 生成编码表:将每个字符和对应的编码存储在一个编码表中,以便解压时查找。
5. 进行编码:根据生成的编码表,将需要编码的数据转换成对应的编码。
Huffman编码的特点是每个字符的编码都是唯一的,没有前缀码。
这意味着在解码时,只需要按照编码表,从根节点开始进行匹配,逐个字符解码,直到找到对应的字符为止。
由于Huffman编码利用了字符出现的频率,将频率高的字符使用较短的编码,这样可以大幅度减少编码后的数据量,从而实现了数据的压缩效果。
霍夫曼解码原理
![霍夫曼解码原理](https://img.taocdn.com/s3/m/cf9197d46aec0975f46527d3240c844768eaa044.png)
霍夫曼解码原理霍夫曼编码是一种高效的二进制编码算法,广泛应用于数据压缩和通信领域。
它通过建立霍夫曼树和构建解码树,实现了数据的快速编码和解码。
以下是霍夫曼解码原理的详细介绍:1. 建立霍夫曼树霍夫曼树是一种特殊的二叉树,它的每个叶子节点都代表一个字符,而每个非叶子节点则代表一个前缀码。
在建立霍夫曼树时,首先需要将所有字符按照频率从大到小排序,然后根据排序结果构建树。
具体步骤如下:(1) 将所有字符按照频率从大到小排序;(2) 创建两个节点,分别代表左子树和右子树,将排序后的前两个节点分别作为左右子节点;(3) 重复步骤2,直到所有字符都被分配到树中。
2. 计算权值在霍夫曼编码中,每个字符的权值是根据它在原始数据中出现的频率来计算的。
具体来说,一个字符的权值等于它的频率乘以一个固定的除数(通常为2的整数次幂),再取整得到一个整数。
这些权值将被用于构建霍夫曼树和生成霍夫曼码。
3. 构建解码树解码树是霍夫曼树的逆过程,它从霍夫曼树的根节点开始,按照霍夫曼树的左子树、右子树的顺序遍历,直到到达叶子节点为止。
在遍历过程中,每个节点代表的字符将被存储下来,最终形成一个解码序列。
4. 解码解码是编码的反过程,它根据接收到的霍夫曼码和霍夫曼树,恢复出原始数据。
具体步骤如下:(1) 从霍夫曼树的根节点开始遍历;(2) 根据当前节点的左子树和右子树的权值,判断下一个要遍历的节点是左子树还是右子树;(3) 重复步骤2,直到遍历到叶子节点;(4) 将叶子节点代表的字符拼接起来,形成解码后的原始数据。
总之,霍夫曼解码是一种高效的编码解码算法,具有较高的压缩比和解码速度。
在实际应用中,可以根据具体需求选择不同的优化策略,如动态码长、可变长度的编码等,以满足不同的应用场景需求。
霍夫曼定理
![霍夫曼定理](https://img.taocdn.com/s3/m/409ff7fc185f312b3169a45177232f60ddcce7fc.png)
霍夫曼定理
霍夫曼定理是在二十世纪四十年代提出的一种经典数学定理,由德国数学家克劳德霍夫曼提出,他的贡献也改变了计算机科学的发展历史。
霍夫曼定理描述的是一种比特编码的数学原理,它将字符串用简单的对称符号序列表示出来,既可以识别出原始字符串,而且具有较小的数据量。
此外,它提出了一种非常容易识别错误的数据编码方法,在现代的计算机系统中有着重要的应用。
其原理是:如果把某些数据编码成比特序列,并且该序列的长度为2的幂次方(例如2、4、8、16……),那么这个序列就称为“霍夫曼编码”,也就是霍夫曼定理描述的编码。
霍夫曼定理的核心思想是在编码过程中能够有效地利用信号之
间的冗余信息,从而形成更简短的编码。
它将比特分装成若干段,在每一段内采用不同的编码技术,并将最常出现的比特对应最短的编码,最少出现的比特对应最长的编码,从而达到压缩的效果。
除此之外,霍夫曼定理还提出了一种能够有效保护传输数据的冗余编码技术,即校验码技术。
校验码是一种特殊的二进制数据,可以通过对发送数据添加一定的调节码来检测接收到的数据是否有错误。
例如,在把发送数据“1010”转换成霍夫曼编码“011”时,会在编
码后加上校验码“1”,使得发送的编码数据变成“0111”,这样在接
收方接收到数据后,就可以通过检测校验码是否正确来判断是否有错误。
因此,霍夫曼定理在计算机系统中占据着重要的位置,它不仅能够有效地压缩数据,而且可以提高传输的精确度和安全性,保证数据的准确性。
从早期的信息传输到现代网络技术,霍夫曼定理始终在这一过程中发挥着重要作用,起着积极的促进作用,极大地满足了当前社会对数据压缩和信息安全的需要,为信息系统的发展贡献了自己的力量。
霍夫曼编码c语言
![霍夫曼编码c语言](https://img.taocdn.com/s3/m/f8d7c94091c69ec3d5bbfd0a79563c1ec5dad7fe.png)
霍夫曼编码c语言霍夫曼编码是一种用于数据压缩的编码技术,它通过重新组织数据中的符号来减少传输或存储数据所需的比特数。
在C语言中实现霍夫曼编码需要掌握数据结构、算法和编码理论的基础知识。
一、霍夫曼编码原理霍夫曼编码的基本原理是利用符号出现的频率来构建一个最优的编码方案,使得编码后的比特率最小。
在霍夫曼图中,每个符号对应一个唯一的路径,路径上的节点表示该符号可能出现的概率。
通过选择概率较大的路径,可以获得较短的编码,从而实现数据压缩。
二、C语言实现霍夫曼编码以下是一个简单的C语言实现霍夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<stdbool.h>//定义霍夫曼树节点结构体typedefstructNode{charsymbol;//符号structNode*left;//左子节点structNode*right;//右子节点intfrequency;//符号频率}Node;//构建霍夫曼树函数Node*buildHuffmanTree(intfrequencies[],intn){//合并相同频率的节点for(inti=0;i<n-1;i++){for(intj=i+1;j<n;j++){if(frequencies[i]==frequencies[j]){ Node*temp=frequencies[i]; frequencies[i]=frequencies[j]; frequencies[j]=temp;mergeNodes(frequencies,i,j);}}}//构建霍夫曼树Node*root=NULL;for(inti=0;i<n;i++){if(root==NULL){root=frequencies[i];}else{Node*child=frequencies[i];child->left=root;root->right=child;root=child;}}returnroot;}//合并两个节点的函数voidmergeNodes(intfrequencies[],inti,intj){frequencies[i]=frequencies[j];//合并节点频率frequencies[j]=NULL;//移除多余节点}//输出霍夫曼编码函数voidprintCodes(Node*root,char*codes[],intindex){if(root==NULL){//如果节点为空,输出编码为空字符串printf("%s",codes[index]);return;}elseif(root->left!=NULL){//如果节点左子节点不为空,输出左子节点的编码作为前缀printCodes(root->left,codes,index*2+1);}elseif(root->right!=NULL){//如果节点右子节点不为空,输出右子节点的编码作为前缀(可用作解码的辅助信息)printCodes(root->right,codes,index*2+2);}else{//如果节点为叶子节点,输出节点的符号作为编码的前缀(去掉重复前缀)并输出当前编码的长度(作为该符号的出现次数)intfreq=root->frequency;//当前符号频率(去掉重复前缀后的频率)while(codes[index]!='\0'){//将前缀放入已使用的字符串数组中以供其他叶子节点使用,重复前缀使用最少的次数(去除重复)并输出当前编码长度和符号本身作为输出结果index--;//指针向后移动一位,直到指针指向'\0'字符为止(已使用的字符串数组)或遇到NULL字符为止(编码数组结束)并返回编码长度和符号本身作为输出结果供其他叶子节点使用和参考。
霍夫曼编码算法
![霍夫曼编码算法](https://img.taocdn.com/s3/m/54dea572ff4733687e21af45b307e87101f6f8ae.png)
霍夫曼编码算法介绍霍夫曼编码是一种用于数据压缩的算法,由大数学家霍夫曼在1952年提出。
它采用变长编码的方式,将频率高的字符用较短的码字表示,频率低的字符用较长的码字表示,从而实现压缩数据的目的。
霍夫曼编码广泛应用于图像、音频、视频等领域,是现代数字通信的基础。
基本原理霍夫曼编码的基本原理是通过建立一颗霍夫曼树来实现对字符的编码和解码。
具体步骤如下:1.统计字符出现的频率。
遍历待编码的数据,记录每个字符出现的频率。
2.构建霍夫曼树。
将频率作为节点权值,构建一颗二叉树。
频率越高的节点越靠近根节点。
3.分配编码。
从根节点出发,每次遇到左子树就加0,遇到右子树就加1,直到叶子节点。
将路径上的0和1组合起来就得到了字符的编码。
4.生成霍夫曼编码表。
遍历霍夫曼树的所有叶子节点,将每个字符及其对应的编码存储在编码表中。
5.进行编码和解码。
使用生成的霍夫曼编码表,将待编码的数据转换成对应的编码。
解码时,通过从霍夫曼树的根节点开始,依次读取编码位,直到叶子节点得到原始字符。
优势与应用•高效的数据压缩能力。
由于频率高的字符用较短的码字表示,频率低的字符用较长的码字表示,霍夫曼编码可以大幅减少数据的存储空间。
•具有良好的可扩展性。
由于霍夫曼编码基于构建树的思想,可以根据实际应用需要对应用领域的数据进行定制化的编码。
•广泛应用于图像、音频、视频等领域。
霍夫曼编码可以有效地压缩这些类型的数据,减小文件大小,提高传输速度。
•在网络传输中的应用。
霍夫曼编码可以缩短数据传输时间,减少网络带宽消耗。
示例和示意图使用霍夫曼编码进行数据压缩的步骤1.统计字符出现的频率。
字符频率A 4B 2C 1D 1E 62.构建霍夫曼树。
3.分配编码。
字符频率编码A 4 00B 2 01C 1 100D 1 101E 6 114.生成霍夫曼编码表。
字符编码A 00B 01C 100D 101E 115.进行编码和解码。
待编码数据:ABBDCEEE编码后的数据:01000111001111解码后的数据:ABBDCEEE总结霍夫曼编码是一种高效的数据压缩算法,通过根据字符出现的频率构建霍夫曼树,并将每个字符分配一个唯一的编码,实现了对数据的压缩和解压缩。
霍夫曼编码的原理
![霍夫曼编码的原理](https://img.taocdn.com/s3/m/99e06919e3bd960590c69ec3d5bbfd0a7956d510.png)
霍夫曼编码的原理
霍夫曼编码是一种变长编码方式,它通过将出现频率较高的字符用较
短的编码表示,从而达到压缩数据的目的。
霍夫曼编码的原理可以分
为以下几个步骤:
1. 统计字符出现的频率
在进行霍夫曼编码之前,需要先对待编码的文本进行字符频率统计。
统计过程中,可以使用哈希表等数据结构来记录每个字符出现的次数。
2. 构建霍夫曼树
在得到每个字符的频率之后,需要将它们构建成一棵二叉树——霍夫
曼树。
构建过程中,首先将所有字符看作是单独的节点,然后按照它
们出现频率从小到大依次合并成更大的节点。
合并过程中,新节点的
权值为两个子节点权值之和。
最终得到一棵只有一个根节点、所有叶
子节点都代表一个字符、且权值最小的二叉树——霍夫曼树。
3. 给每个字符分配编码
在得到霍夫曼树之后,需要给每个字符分配唯一的编码。
对于每个叶
子节点(即代表一个字符),从它所在位置开始向上遍历整棵树,每次向左走就在编码的末尾添加0,每次向右走就在编码的末尾添加1。
最终得到每个字符对应的霍夫曼编码。
4. 进行压缩
在得到每个字符的霍夫曼编码之后,可以将原始文本中的每个字符都用它对应的霍夫曼编码来代替。
由于不同字符的编码长度不同,所以用霍夫曼编码来代替原始字符后,可以实现数据压缩。
总结:
霍夫曼编码是一种通过将出现频率较高的字符用较短的编码表示来达到压缩数据的目的。
它通过构建一棵二叉树——霍夫曼树,并给每个叶子节点分配唯一的编码来实现数据压缩。
由于不同字符的出现频率不同,所以使用霍夫曼编码可以有效地减少数据存储空间。
霍夫曼编码原理
![霍夫曼编码原理](https://img.taocdn.com/s3/m/c4499d93a48da0116c175f0e7cd184254b351bfe.png)
霍夫曼编码原理霍夫曼编码是一种被广泛应用于数据压缩领域的编码原理,它通过对不同符号赋予不同长度的编码来实现数据压缩。
这种编码方式是由大卫·霍夫曼在1952年提出的,被认为是一种高效的编码方式,可以在不损失数据的情况下显著减小数据的存储空间。
在霍夫曼编码中,频率较高的符号被赋予较短的编码,而频率较低的符号则被赋予较长的编码,这样就能够实现对数据的高效压缩。
这种编码方式的核心思想是利用频率分布来设计编码,使得出现频率高的符号具有较短的编码,从而减小整体的编码长度。
为了更好地理解霍夫曼编码原理,我们可以通过一个简单的例子来进行说明。
假设有一个由A、B、C、D四个符号组成的消息,它们的出现频率分别为30%、30%、20%、20%。
我们可以利用霍夫曼编码来对这些符号进行编码,其中出现频率高的符号A和B被赋予较短的编码,而出现频率低的符号C和D被赋予较长的编码。
通过这种方式,我们可以实现对消息的高效压缩,从而减小存储空间的占用。
在实际应用中,霍夫曼编码被广泛应用于数据压缩领域,特别是在图像、音频和视频等多媒体数据的压缩中。
由于多媒体数据通常具有较高的冗余性和较大的数据量,采用霍夫曼编码可以有效地减小数据的存储空间,从而提高数据的传输和存储效率。
除了在数据压缩领域,霍夫曼编码还被广泛应用于通信领域。
在数字通信中,为了提高数据传输的效率和可靠性,通常会采用霍夫曼编码来对数据进行压缩和编码,从而减小数据传输的时间和成本。
总的来说,霍夫曼编码原理是一种高效的编码方式,它通过对不同符号赋予不同长度的编码来实现数据压缩。
这种编码方式在数据压缩和通信领域有着广泛的应用,能够有效地减小数据的存储空间并提高数据传输的效率和可靠性。
因此,深入理解霍夫曼编码原理对于数据处理和通信技术的研究具有重要意义。
霍夫曼编码的举例
![霍夫曼编码的举例](https://img.taocdn.com/s3/m/60ae240bb80d6c85ec3a87c24028915f804d84ab.png)
霍夫曼编码1. 概述霍夫曼编码是一种用于数据压缩的算法,通过将频率较高的字符用较短的编码表示,从而实现对数据的高效压缩。
该编码算法由霍夫曼(David A. Huffman)于1952年提出,被广泛应用于通信、存储等领域。
2. 基本原理霍夫曼编码的基本思想是根据字符出现的频率来构建一棵二叉树,出现频率越高的字符距离根节点越近,从而对其进行更短的编码。
编码过程中,将字符与其对应的编码一一映射,使得每个字符的编码都是唯一的,且没有编码是另一个编码的前缀。
3. 编码过程下面以一个简单的例子来说明霍夫曼编码的过程。
假设有一个字符串:“ABBCCCDDDDEEEEE”,我们需要对其进行编码。
3.1. 统计字符频率首先,我们需要统计每个字符在字符串中出现的频率。
统计结果如下:字符频率A 1B 2C 3D 4E 53.2. 构建霍夫曼树根据字符的频率,我们可以构建一棵霍夫曼树。
构建过程如下:1.将频率最低的两个字符作为叶子节点,创建一个父节点,父节点的频率为两个子节点的频率之和。
2.将父节点插入到频率表中,并删除原来的两个子节点。
3.重复上述步骤,直到只剩下一个节点,即为根节点。
构建过程如下图所示:15/ \5 10/ \ / \A B C D/ \E E3.3. 生成编码表根据霍夫曼树,我们可以生成字符与其对应编码的映射表。
生成过程如下:1.从根节点开始,沿着左子树路径为0,沿着右子树路径为1,将路径上经过的编码记录下来。
2.重复上述步骤,直到遍历到叶子节点,将叶子节点对应的字符和编码记录下来。
生成的编码表如下:字符编码A 00B 01C 10D 11E 11注意:由于霍夫曼树中的叶子节点只有一个字符,因此没有编码会是另一个编码的前缀。
3.4. 进行编码使用生成的编码表,我们可以将原始字符串进行编码。
编码过程如下:将原始字符串中的每个字符替换为其对应的编码,得到编码后的字符串。
原始字符串:“ABBCCCDDDDEEEEE”编码后的字符串:“010101101010101011111111111”3.5. 进行解码使用生成的编码表,我们可以将编码后的字符串进行解码。
霍夫曼编码
![霍夫曼编码](https://img.taocdn.com/s3/m/fb4c285277232f60ddcca12c.png)
霍夫曼编码近期准备写一个项目需要用到此类知识,于是在网上搜索到一些资料并且学习了。
现在把自己的学习笔记和一些心得体会写出来和大家分享一下。
编码原理:霍夫曼编码主要是用于对文件的压缩操作。
在进行压缩编码之前,先把文件内出现的字符全部的浏览一遍(就是扫描),然后统计其中每个字符出现的频率,出现频率较多的用较短的编码表示,出现频率较少的用较长的编码表示。
(因为原先的每个字符都是用8位表示的,而这八位字节表示的值就只有256种,所以当有大量的数据的时候重复的情况是很多的。
)现在把出现较多字符用远远少于8位的字节来表示,又因为文件中出现较多的字符频率多于出现较低的字符的频率,文件因此而被压缩。
具体编码方法:每种编码都有自己的编码方法和表现形式,霍夫曼编码也不例外。
在此我想用二叉树来表示霍夫曼的编码。
为什么选用二叉树,下面我来具体简述一下:在二叉树中,我们用叶子所在的地方来编码要表示的字符,在二叉树中向左分支的用0表示,向右分支的用1表示;例如12|----------------------------| |A(4)8------------| |B(5)c(3)所以A的编码是0,B为10,C为11,因为A出现了4次,B出现了5次,C出现了3次。
所以4*1+5*2+3*2=20,如果此时把A的位置和B的位置交换12|----------------------------| |B(5)7------------| |A(4)c(3)那此时A的编码是10,B为0,C为11所以5*1+4*2+3*2=19,此时字节数比原来少了,这就是压缩操作,霍夫曼的编码方法就是实现这种二叉树排列的变换。
没有别的形式的二叉树比这个二叉树占用的资源更少,这样的二叉树我们称之为最优二叉树。
而霍夫曼编码采用的就是最优二叉树这种表示形式,霍夫曼提出在搜索到的字符使用频率(次数)中,取出其中最小的两个相加,然后去掉最小的两个把相加的结果作为一个父节点放到原数组中,然后再取出其中最小的2个相加得到的结果作为这2个数的父节点........如此反复,直到最后2个数相加的频率为1.这样得到的就是一个最优二叉树。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
霍夫曼编码四川大学计算机学院2009级戚辅光【关键字】霍夫曼编码原理霍夫曼译码原理霍夫曼树霍夫曼编码源代码霍夫曼编码分析霍夫曼编码的优化霍夫曼编码的应用【摘要】哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。
uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman 编码。
哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。
它属于可变代码长度算法一族。
意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。
因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
【正文】引言哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。
uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
霍夫曼编码原理:霍夫曼编码的基本思想:输入一个待编码的串,首先统计串中各字符出现的次数,称之为频次,假设统计频次的数组为count[],则霍夫曼编码每次找出count数组中的值最小的两个分别作为左右孩子,建立他们的父节点,循环这个操作2*n-1-n(n是不同的字符数)次,这样就把霍夫曼树建好了。
建树的过程需要注意,首先把count数组里面的n个值初始化为霍夫曼树的n个叶子节点,他们的孩子节点的标号初始化为-1,父节点初始化为他本身的标号。
接下来是编码,每次从霍夫曼树的叶子节点出发,依次向上找,假设当前的节点标号是i,那么他的父节点必然是myHuffmantree[i].parent,如果i是myHuffmantree[i].parent 的左节点,则该节点的路径为0,如果是右节点,则该节点的路径为1。
当向上找到一个节点,他的父节点标号就是他本身,就停止(说明该节点已经是根节点)。
还有一个需要注意的地方:在查找当前权值最小的两个节点时,那些父节点不是他本身的节点不能考虑进去,因为这些节点已经被处理过了。
霍夫曼树:下面是字符串agdfaghdabsb的霍夫曼编码的霍夫曼树:字符串:由上面的霍夫曼树可知各个字符的编码如下:a: 01b:010d:011f:100g:101h:110s:111所以整个串的编码为:011010111000110111001101010111010霍夫曼译码原理:对于霍夫曼的译码,可以肯定的是其译码结果是唯一的。
证明:因为霍夫曼编码是根据霍夫曼树来确定的,霍夫曼树是一棵二叉树,编码的时候是从树根一直往下走,直到走到叶子节点为止,在其经过的路径上,如果是树的左子树则为0,否则为1。
因为每一次都要走到树的叶子节点,多以不可能存在两个编码a和b,使得a是b的前缀或者b是a的前缀。
所以编码一定可以唯一确定。
根据上面的结论,我们可以很清楚地直到译码的方法:定义两个指针p1,p2,P1指向当前编码的开始位置,P2指向当前编码的位置,如果P1-P2这一段编码能在编码库里面找到完全对应的编码结果,则译码成功,该段编码的译码结果就是与编码库里完全对应的编码的字符。
循环次操作,直到译码结束!例一:假设有一段字符含有a,,c,d三个字符,经过编码之后三个字符对应的编码结果分别为:a:01c:010d:011现在给你一段编码0110101,要求将其译码!按照上面介绍的方法我们可以直到:编码的前三个字符是且仅是d的编码,所以011译码为d,依次译码可得整串的译码结果为daa霍夫曼编码源代码:#include<iostream>#include<cstring>#include<algorithm>#include<map>using namespace std;#define INF 0x7fffffff //无穷大struct Huffmantree //霍夫曼树的节点{int weight;int parent,ld,rd;};struct myNode{char ch;int num;};struct mycode //字符和其对应的编码{char ch; //字符int s[50]; //ch的编码int len; //编码长度};int nNode; //叶子节点数目int totalNode; //霍夫曼树的总节点个数char toCode[100000] ; //待编码的字符串myNode myToCode[100000]; //待编码的字符串和权值int weightOfToCode[100000] ; //字符串的权值!Huffmantree myHuffmantree[1000000]; //霍夫曼树(数组模拟)char allchar[1000000]; //所哟出现过的字符mycode coder[1000000]; //字符与对应的编码int Len; //待编码的字符的总长度int Coding[100000]; //译码之后的01串int lenOfCoding ; //01串的长度void build(int n); //建立霍夫曼树void select(int &a,int &b); //选择两个权值最小的节点void Code(); //编码void printCode(); //打印编码void deCode(); //译码int match(int l,int h);int main(){int i;cout<<"\n=============================霍夫曼编码程序=============================";cout<<"\n 作者:戚辅光"<<endl;cout<<" 时间:2010-11-23"<<endl;while(1){printf("请输入待编码的字符串\n");int flag=0;gets(toCode);int len=strlen(toCode);if(len==1){flag=1;}Len=len;map<char,int>myMap;for(i=0;i<len;i++) //统计字符串中各字符出现的频次!{myMap[toCode[i]]++;}map<char,int>::iterator iter;int h=1;for(iter=myMap.begin();iter!=myMap.end();iter++){myToCode[h].ch=iter->first;allchar[h]=iter->first;weightOfToCode[h]=iter->second;myToCode[h++].num=iter->second;}nNode=h-1; //叶子节点个数cout<<"----------------------字符统计如下--------------------------------------"<<endl;cout<<" 字符次数"<<endl;for(i=1;i<h;i++) //显示将要编码的字符串中的各字符和他出现的次数!{cout<<" "<<myToCode[i].ch<<" "<<myToCode[i].num<<endl;}cout<<endl;totalNode=nNode; //totalNode初始值为nNodecout<<"-----------霍夫曼树节点信息如下(子节点为-1表示是叶子节点)---------------"<<endl<<endl;build(nNode);cout<<endl;Code();cout<<"\n-------------------------字符串的编码结果如下--------------------------\n";printCode();cout<<"\n-------------------------01串的译码结果如下-----------------------------\n";deCode();cout<<"\n是否继续?(Y/N)\n";char con[10];cin>>con;char fang=toupper(con[0]);if(fang=='N'){break;}getchar();}return 0;}void build(int n) //建立霍夫曼树{int i;int m=2*n-1; //n个叶子节点的霍夫曼树总节点数为2*n-1for(i=1;i<=n;i++) //初始化霍夫曼数组{myHuffmantree[i].weight=weightOfToCode[i]; //叶子节点权值为字符出现次数myHuffmantree[i].ld=-1; //叶子节点没有左孩子myHuffmantree[i].rd=-1; //叶子节点没有右孩子myHuffmantree[i].parent=i; //叶子节点父节点先初始化为他本身}for(i=n+1;i<=m;i++){int a,b;select(a,b);myHuffmantree[a].parent=i;myHuffmantree[b].parent=i;myHuffmantree[i].ld=a;myHuffmantree[i].rd=b;myHuffmantree[i].weight=myHuffmantree[a].weight+myHuffmantree[b].weight;myHuffmantree[i].parent=i;}for(i=1;i<=totalNode;i++){printf("节点:%3d 权值:%3d 左节点:%3d 右节点:%3d 父节点:%3d \n",i,myHuffmantree[i].weight,myHuffmantree[i].ld,myHuffmantree[i].rd,myHuffmantree[i].pare nt);}}void Code() //编码{int i,j;int numOfCode[100000];cout<<"--------------------------各字符编码结果如下----------------------------"<<endl;if(Len==1){cout<<toCode[0]<<" : "<<"0\n";return ;}for(i=1;i<=nNode;i++){j=i;int h=0;while(myHuffmantree[j].parent!=j){int x=j;j=myHuffmantree[j].parent;if(myHuffmantree[j].ld==x){numOfCode[h++]=0;}else if(myHuffmantree[j].rd==x){numOfCode[h++]=1;}}cout<<" "<<allchar[i]<<" : ";int x=0;coder[i].len=h;coder[i].ch=allchar[i];for(int k=h-1;k>=0;k--){coder[i].s[x++]=numOfCode[k];printf("%d",numOfCode[k]);}cout<<endl;}}void select(int &a,int &b) //选择两个权值最小的节点{int i;int min1=INF;int min2=INF;int sign1=1; //最小值的下标int sign2=2; //次小值的下标for(i=1;i<=totalNode;i++){if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点{if(myHuffmantree[i].weight<min1){min1=myHuffmantree[i].weight;sign1=i;}}}for(i=1;i<=totalNode;i++){if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点{if(myHuffmantree[i].weight<min2&&i!=sign1){min2=myHuffmantree[i].weight;sign2=i;}}}a=sign1;b=sign2;totalNode++; //总节点数加1}void printCode() //打印编码结果!{int i;if(Len==1) //长度为1的时候特殊考虑{cout<<"0\n";return ;}int h=0;for(i=0;i<Len;i++){for(int j=1;j<=nNode;j++){if(toCode[i]==coder[j].ch){for(int k=0;k<coder[j].len;k++){printf("%d",coder[j].s[k]);Coding[h++]=coder[j].s[k];}}}}lenOfCoding=h;cout<<endl;}void deCode() //译码{int i,j;int begin=0;for(i=0;i<lenOfCoding;i++){if(match(begin,i)!=-1){int x=match(begin,i);printf("%c",coder[x].ch);begin=i+1;}}printf("\n");}int match(int l,int h) //译码的辅助函数(寻找匹配){int i,j,k;int flag=0;for(i=1;i<=nNode;i++){if(coder[i].len!=h-l+1){continue;}k=l;for(j=0;j<coder[i].len;j++){if(Coding[k]!=coder[i].s[j]){break;}if(j==coder[i].len-1){flag=1;goto ok;}k++;}}ok:;if(flag==1) //查找成功返回对应的下表{return i;}else //查找不成功返回-1;{return -1;}}霍夫曼编码代码分析:1.运行环境:win7操作系统,Inter(R) Core(TM) Duo **************.20GHz内存:2.00GB,32位操作系统2.程序运行结果:3. 程序功能模块分析:整个程序包含6个函数:A.void build(int n);B.void select(int &a,int &b);C.void Code();D.void printCode();E.void deCode();F.int match(int l,int h);其中A是用来建立霍夫曼树,B是在A中调用的一个辅助函数,用来查找两个权值最小的节点的下标,C是对字符串编码,D是现实编码结果,E是译码01串,F是E的辅助函数,用来寻找编码的匹配。