霍夫曼编码的C语言实现
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《信息处理与编码》结课大作业
学号: 班级: 姓名: 成绩:
霍夫曼编码的C语言实现 1.编码原理
霍夫曼码由霍夫曼树构造,平均码长是霍夫曼树的带权
路径长度,由于霍夫曼树是权最小的树,故其压缩效果最好。 霍夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常 应用于数据压缩。 在计算机信息处理中,“霍夫曼编码”是 一种一致性编码法(又称"熵编码法"),用于数据的无损耗压 缩。这一术语是指使用一张特殊的编码表将源字符(例如某文 件中的一个符号)进行编码。这张编码表的特殊之处在于,它 是根据每一个源字符出现的估算概率而建立起来的。 霍夫曼码是用概率匹配方法进行信源编码。有两个明显 特点:一是保证了概率大的符号对应于短码,概率小的对应于 长码,充分利用了短码;二是缩减信源的最后二个码字总是最 后一位不同,从而保证了霍夫曼码是即时码。 霍夫曼变长码的效率很高,它可以单个信源符号编码或 用L较小的信源序列编码,对编码器的设计来说也易实现,但 要注意,更高效率的编码仍须按长序列来计算,这样才能使平 均码字降低。
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;
如表二HuffmanCode: Number 1 2 3 Weight 5 29 7 Code 0110 10 1110
4 5 6 7 8
8 14 23 3 11
1111 110 00 0111 010
} 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=(HuffmanCode)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; } MinCode Select(HuffmanTree HT,unsigned int n) { unsigned int min,secmin; unsigned int temp; unsigned int i,s1,s2,tempi;
typedef struct { unsigned int s1; unsigned int s2; } MinCode; void Error(char *message); HuffmanCode HuffmanCoding(HuffmanTree HC,unsigned int *w,unsigned int n); MinCode Select(HuffmanTree HT,unsigned int n); void Error(char *message) { clrscr(); fprintf(stderr,"Error:%s\n",message); exit(1); } HuffmanCode HuffmanCoding(HuffmanTree HC,unsigned int *w,unsigned int n) { unsigned int i,s1=0,s2=0; HuffmanTree p; char *cd; unsigned int f,c,start,m; MinCode min; HT,HuffmanCode HT,HuffmanCode
Biblioteka Baidu
2.霍夫曼编码的步骤
(l)将信号源的符号按照出现概率递减的顺序排列。 (2)将两个最小出现概率进行合并相加,得到的结果作为 新符号的出现概率。 (3)重复进行步骤1和2直到概率相加的结果等于1为止。 (4)在合并运算时,概率大的符号用编码0表示,概率小
的符号用编码1表示。 (5)记录下概率为1处到当前信号源符号之间的0,l序 列,从而得到每个符号的编码。 例如: 设信号源为 s={s1, s2, s3, s4, s5} 对应的概率为p={0.25,0.22,0.20, 0.18,0.15}。 根据字符出现的概率来构造平均长度最短的异字头码字。 霍未曼编码通常采用两次扫描的办法,第一次扫描得到统计结 果,第二次扫描进行编码。
if(n<=1) Error("Code too small!"); m=2*n-1; HT=(HuffmanTree)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].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight;
printf("w[%d]=",i); scanf("%d",&w[i]); } HC=HuffmanCoding(HT,HC,w,n); printf("HuffmanCode:\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]); }
程序运行: 首先用户先输入一个数n,以实现n个节点的Huffman Tree 之后输入权值w[1]~w[n],注意是unsigned int型数值。 然后程序自动生成Huffman Tree的存储形式的一张表格。 最后是Huffman Coding。
Sample Input: Input n: 8 Enter weight: w[1]=5 w[2]=29 w[3]=7 w[4]=8 w[5]=14 w[6]=23 w[7]=3
3.编码程序
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <conio.h> typedef struct { unsigned int weight; nsigned int parent,lchild,rchild; } HTNode,*HuffmanTree; typedef char **HuffmanCode;
w[8]=11 Sample Output: : Number weight 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 5 29 7 8 14 23 3 11 8 15 19 29 42 58 100 如表1 HT List parent 9 14 10 10 12 13 9 11 11 12 13 14 15 15 0 lchild 0 0 0 0 0 0 0 0 1 3 8 5 6 2 13 0 0 7 4 9 10 11 12 14 0 0 0 0 rchild 0 0
s2=i; } if(s1>s2) { temp=s1; s1=s2; s2=temp; } code.s1=s1; code.s2=s2; return code; } void main() { HuffmanTree HT=NULL; HuffmanCode HC=NULL; unsigned int *w=NULL; unsigned int i,n; clrscr(); printf("Input n:\n"); scanf("%d",&n); w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *)); w[0]=0; printf("Enter weight:\n"); for(i=1;i<=n;i++) {
学号: 班级: 姓名: 成绩:
霍夫曼编码的C语言实现 1.编码原理
霍夫曼码由霍夫曼树构造,平均码长是霍夫曼树的带权
路径长度,由于霍夫曼树是权最小的树,故其压缩效果最好。 霍夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常 应用于数据压缩。 在计算机信息处理中,“霍夫曼编码”是 一种一致性编码法(又称"熵编码法"),用于数据的无损耗压 缩。这一术语是指使用一张特殊的编码表将源字符(例如某文 件中的一个符号)进行编码。这张编码表的特殊之处在于,它 是根据每一个源字符出现的估算概率而建立起来的。 霍夫曼码是用概率匹配方法进行信源编码。有两个明显 特点:一是保证了概率大的符号对应于短码,概率小的对应于 长码,充分利用了短码;二是缩减信源的最后二个码字总是最 后一位不同,从而保证了霍夫曼码是即时码。 霍夫曼变长码的效率很高,它可以单个信源符号编码或 用L较小的信源序列编码,对编码器的设计来说也易实现,但 要注意,更高效率的编码仍须按长序列来计算,这样才能使平 均码字降低。
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;
如表二HuffmanCode: Number 1 2 3 Weight 5 29 7 Code 0110 10 1110
4 5 6 7 8
8 14 23 3 11
1111 110 00 0111 010
} 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=(HuffmanCode)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; } MinCode Select(HuffmanTree HT,unsigned int n) { unsigned int min,secmin; unsigned int temp; unsigned int i,s1,s2,tempi;
typedef struct { unsigned int s1; unsigned int s2; } MinCode; void Error(char *message); HuffmanCode HuffmanCoding(HuffmanTree HC,unsigned int *w,unsigned int n); MinCode Select(HuffmanTree HT,unsigned int n); void Error(char *message) { clrscr(); fprintf(stderr,"Error:%s\n",message); exit(1); } HuffmanCode HuffmanCoding(HuffmanTree HC,unsigned int *w,unsigned int n) { unsigned int i,s1=0,s2=0; HuffmanTree p; char *cd; unsigned int f,c,start,m; MinCode min; HT,HuffmanCode HT,HuffmanCode
Biblioteka Baidu
2.霍夫曼编码的步骤
(l)将信号源的符号按照出现概率递减的顺序排列。 (2)将两个最小出现概率进行合并相加,得到的结果作为 新符号的出现概率。 (3)重复进行步骤1和2直到概率相加的结果等于1为止。 (4)在合并运算时,概率大的符号用编码0表示,概率小
的符号用编码1表示。 (5)记录下概率为1处到当前信号源符号之间的0,l序 列,从而得到每个符号的编码。 例如: 设信号源为 s={s1, s2, s3, s4, s5} 对应的概率为p={0.25,0.22,0.20, 0.18,0.15}。 根据字符出现的概率来构造平均长度最短的异字头码字。 霍未曼编码通常采用两次扫描的办法,第一次扫描得到统计结 果,第二次扫描进行编码。
if(n<=1) Error("Code too small!"); m=2*n-1; HT=(HuffmanTree)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].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight;
printf("w[%d]=",i); scanf("%d",&w[i]); } HC=HuffmanCoding(HT,HC,w,n); printf("HuffmanCode:\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]); }
程序运行: 首先用户先输入一个数n,以实现n个节点的Huffman Tree 之后输入权值w[1]~w[n],注意是unsigned int型数值。 然后程序自动生成Huffman Tree的存储形式的一张表格。 最后是Huffman Coding。
Sample Input: Input n: 8 Enter weight: w[1]=5 w[2]=29 w[3]=7 w[4]=8 w[5]=14 w[6]=23 w[7]=3
3.编码程序
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <conio.h> typedef struct { unsigned int weight; nsigned int parent,lchild,rchild; } HTNode,*HuffmanTree; typedef char **HuffmanCode;
w[8]=11 Sample Output: : Number weight 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 5 29 7 8 14 23 3 11 8 15 19 29 42 58 100 如表1 HT List parent 9 14 10 10 12 13 9 11 11 12 13 14 15 15 0 lchild 0 0 0 0 0 0 0 0 1 3 8 5 6 2 13 0 0 7 4 9 10 11 12 14 0 0 0 0 rchild 0 0
s2=i; } if(s1>s2) { temp=s1; s1=s2; s2=temp; } code.s1=s1; code.s2=s2; return code; } void main() { HuffmanTree HT=NULL; HuffmanCode HC=NULL; unsigned int *w=NULL; unsigned int i,n; clrscr(); printf("Input n:\n"); scanf("%d",&n); w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *)); w[0]=0; printf("Enter weight:\n"); for(i=1;i<=n;i++) {