哈弗曼编码实验报告.docx
- 文档编号:5333395
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:17
- 大小:19.78KB
哈弗曼编码实验报告.docx
《哈弗曼编码实验报告.docx》由会员分享,可在线阅读,更多相关《哈弗曼编码实验报告.docx(17页珍藏版)》请在冰豆网上搜索。
哈弗曼编码实验报告
一.实验目的
1、掌握哈夫曼树的构造和应用
2、利用哈夫曼方法及其编/译码技术实现对传输信息编码/译码系统.
二.实验内容
1、哈夫编码/译码器简介
本例说明,先前快速远距离通信的主要手段是电报,即将需传送的文字转换成由二进制的字符组成的字符串。
在传送电文时,希望总长尽可能地短,如果对每个字符设计长度不等的编码,且让电文中出现次数较多的字符采用尽可能短的编码,以减少经费。
哈夫曼树就是根据此原理设计出来的一种存储结构。
2、问题描述
哈夫曼树很易求出给定字符集及其概率(或频度)分布的最优前缀码。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
该技术一般可将数据文件压缩掉20%至90%,其压缩效率取决于被压缩文件的特征。
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传送电文须预先编码,在接收须将传送来的数据进行译码。
请自行设计实现一个具有初始化、编码、译码、输入/输出等功能的哈夫曼码的编码/译码系统。
并实现以下报文的编码和译码:
“thisprogramismyfavorite”。
3.测试数据
某通信的电文字符集为26个英文字母及空格字符,其出现频度如下表所示:
4、设计思想描述
(1)问题分析。
(2)哈夫曼树中各结点的结构描述(如上图)。
(3)哈夫曼树的存储结构描述。
5、主要算法设计与实现
(1)哈弗曼树的定义(动态分配数组存储哈夫曼树)
typedefstruct{
charch;//键值
intweight;//权值
intselected;//编码值
intparent,lchild,rchild;//各节点的值
}HTNode,*HuffmanTree;//动态分配数组存储哈夫曼树
(2)定义用于译码的树
typedefstructTreeNode{
structTreeNode*lchild;//结构指针
structTreeNode*rchild;
charcode;
chardata;
}TreeNode,*Tree;
(3)哈夫曼树函数的设计
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*&w,intn){//建立哈弗曼树
intm=2*n-1,i,j,s1,s2,start,f;
char*cd;
HuffmanTreep;
if(n<=1)return;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未使用
for(p=HT+1,i=1;i<=n;i++,p++,w++){
p->weight=*(w+1);
p->selected=p->lchild=p->rchild=p->parent=0;
}
for(;i<=m;i++,p++)
p->selected=p->parent=p->lchild=p->rchild=0;
for(i=n+1;i<=m;i++){//建立哈弗曼树
Select(HT,i-1,&s1,&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("\n哈弗曼树表\n");//打印哈弗曼树表
printf("iweightparentlchildrchild\n");
for(p=HT+1,i=1;i<=m;i++,p++)
printf("%2d%6d%6d%6d%6d\n",i,p->weight,p->parent,p->lchild,p->rchild);
printf("\n");
//从叶子到根逆向求每个字符的哈夫曼编码
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量
cd=(char*)malloc(n*sizeof(char));//分配求编码的工作空间
cd[n-1]='\0';//编码结束符
for(i=1;i<=n;i++){//逐个字符求哈夫曼编码
start=n-1;//编码结束位置for(j=i,f=HT[i].parent;f!
=0;j=f,f=HT[f].parent){//从叶子到根逆向求编码
if(HT[f].lchild==j)
cd[--start]='0';
else
cd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);//从cd复制编码到HC
}
free(cd);//释放工作空间
}
(4)对编码函数的设计
voidCodeInput(intn,int*&w,char*&code){//字符及权值的输入
inti;
w=(int*)malloc((n+1)*sizeof(int));//分配权值的工作空间
code=(char*)malloc((n+1)*sizeof(char));//分配字符的工作空间
printf("请输入字符以及权值:
\n");
for(i=1;i<=n;i++){
fflush(stdin);//清除缓从区间
scanf("%c%d",&code[i],&w[i]);
}
}
voidEncoding(Sentence&sentence,char*&code,HuffmanCode&HC,intn){//編码
charc,t,*pp;
inti;
Sentencep,q;
sentence=(Sentence)malloc(sizeof(S));
q=sentence;
q->next=NULL;
printf("请输入待编码的字符串:
\n");
fflush(stdin);
while(scanf("%c",&c)!
=EOF&&c!
='\n'){
for(i=1;i<=n;i++){
t=code[i];
if(c==t){
pp=HC[i];
break;
}
}
for(i=0;pp[i]!
='\0';i++){
p=(Sentence)malloc(sizeof(S));
p->c=pp[i];
q->next=p;
p->next=NULL;
q=p;
}
}
p=sentence->next;
printf("\n编码后的语句:
\n");
while(p!
=NULL){
printf("%c",p->c);
p=p->next;
}
printf("\n");
}
(5)对译码函数的设计
voidDecoding(Sentence&sentence,char*&code,HuffmanCode&HC,Tree&root,intn){//译码
Treep,q;
Sentencer=sentence->next;
inti,j;
charc,*t;
root=(Tree)malloc(sizeof(TreeNode));
root->lchild=NULL;
root->rchild=NULL;
for(i=1;i<=n;i++){
t=HC[i];
q=root;
for(j=0;j c=t[j]; if(q->lchild! =NULL){ if(q->lchild->code==c){ q=q->lchild; } elseif(q->rchild! =NULL){ q=q->rchild; } else{ p=(Tree)malloc(sizeof(TreeNode)); p->lchild=NULL; p->rchild=NULL; p->code=c; if(t[j+1]! ='\0') p->data='n'; else p->data=code[i]; q->rchild=p; q=p; } } else{ p=(Tree)malloc(sizeof(TreeNode)); p->lchild=NULL; p->rchild=NULL; p->code=c; if(t[j+1]! ='\0') p->data='n'; else p->data=code[i]; q->lchild=p; q=p; } } } q=root; printf("\n解码后的语句: \n"); while(r! =NULL){ c=r->c; if(q->lchild! =NULL){ if(q->lchild->code==c){ q=q->lchild; if(q->lchild==NULL){ printf("%c",q->data); q=root; } } else{ q=q->rchild; if(q->lchild==NULL){ printf("%c",q->data); q=root; } } } else{ printf("%c",q->data); q=root; } r=r->next; } printf("\n\n"); return;} 三实验结果 根据此次实验的设计,我们编写出相应的源代码,在运行时可以得到相应的功能: 其运行界面如下图所示: 在上面输入所需输入字符集大小。 如输入26个英文字母及空格时 所得的哈弗曼树(如下图部分)及哈弗曼编码(如下图部分) 当输入带编码语句“thisprogrameismyfavorite”时,按回车,出现其编码后的语句及译码后的语句如下图: 四实验总结 通过本次数据结构的课程设计,我学习了很读我之前上课没懂的知识。 并在老师指导下,我对求哈夫曼树及哈夫曼编码/译码的算法有了更加深刻的了解,更巩固了课堂中学习有关于哈夫曼编码的知识,真正学会一种算法了。 当求解一个算法时,不是拿到问题就不加思索地做,而是首先要先对它有个大概的了解,接着再详细地分析每一步怎么做,无论自己以前是否有处理过相似的问题,只要按照以上的步骤,必定会顺利地做出来。 这次课程设计中我在编辑中犯了不应有的错误,设计统计字符和合并时忘记应该怎样保存保存数据,在老师的指导下改正了错误和疏漏,使我们的程序有了更高的质量。 有时还是会遇到一些这样或那样的问题,在这时就要看团体的力量,遇到困难时我们组会聚集到一块儿合力讨论,尽力把它解决,每次解决了一个问题之后就会给自己多了一份自信,对今后的学习和程序的设计有了更大的信心。 再次我真心的感谢老师对我们的帮助与指导。 我会更加努力学习数据结构方面的知识,来完善自己的学习。 五代码 #include #include #include typedefstruct{ charch; intweight; intselected; intparent,lchild,rchild; }HTNode,*HuffmanTree;//动态分配数组存储哈夫曼树 typedefstructS{ charc; structS*next; }S,*Sentence;//用于待编码的语句 typedefchar**HuffmanCode;//动态分配数组存储哈夫曼编码表 typedefstructTreeNode{ structTreeNode*lchild; structTreeNode*rchild; charcode; chardata; }TreeNode,*Tree;//用于解码的树 voidSelect(HuffmanTree&HT,intposition,int*s1,int*s2){//选择函数 inti,j,t; intp,q; intfirst,second; for(i=1;i<=position;i++) if(HT[i].selected==0){ first=HT[i].weight; break; } for(j=i+1;j<=position;j++) if(HT[j].selected==0){ second=HT[j].weight; break; } if(first>second){ t=first; first=second; second=t; } for(i=j+1;i<=position;i++){ if(HT[i].selected==0){ t=HT[i].weight; if(t second=first; first=t; } elseif(t second=t; } } } for(i=1;i<=position;i++){ if(HT[i].selected==0&&HT[i].weight==first){ HT[i].selected=1; p=i; break; } } for(i=1;i<=position;i++){ if(HT[i].selected==0&&HT[i].weight==second){ HT[i].selected=1; q=i; break; } } if(p>q){ t=q; q=p; p=t; } *s1=p; *s2=q; return; } voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*&w,intn){//建立哈弗曼树 intm=2*n-1,i,j,s1,s2,start,f; char*cd; HuffmanTreep; if(n<=1) return; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未使用 for(p=HT+1,i=1;i<=n;i++,p++,w++){ p->weight=*(w+1); p->selected=p->lchild=p->rchild=p->parent=0; } for(;i<=m;i++,p++) p->selected=p->parent=p->lchild=p->rchild=0; for(i=n+1;i<=m;i++){//建立哈弗曼树 Select(HT,i-1,&s1,&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("\n哈弗曼树表\n");//打印哈弗曼树表 printf("iweightparentlchildrchild\n"); for(p=HT+1,i=1;i<=m;i++,p++) printf("%2d%6d%6d%6d%6d\n",i,p->weight,p->parent,p->lchild,p->rchild); printf("\n"); //从叶子到根逆向求每个字符的哈夫曼编码 HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量 cd=(char*)malloc(n*sizeof(char));//分配求编码的工作空间 cd[n-1]='\0';//编码结束符 for(i=1;i<=n;i++){//逐个字符求哈夫曼编码 start=n-1;//编码结束位置 for(j=i,f=HT[i].parent;f! =0;j=f,f=HT[f].parent){//从叶子到根逆向求编码 if(HT[f].lchild==j) cd[--start]='0'; else cd[--start]='1'; } HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间 strcpy(HC[i],&cd[start]);//从cd复制编码到HC } free(cd);//释放工作空间 } voidCodeInput(intn,int*&w,char*&code){//字符及权值的输入 inti; w=(int*)malloc((n+1)*sizeof(int));//分配权值的工作空间 code=(char*)malloc((n+1)*sizeof(char));//分配字符的工作空间 printf("请输入字符以及权值: \n"); for(i=1;i<=n;i++){ fflush(stdin);//清除缓从区间 scanf("%c%d",&code[i],&w[i]); } } voidEncoding(Sentence&sentence,char*&code,HuffmanCode&HC,intn){//编码 charc,t,*pp; inti; Sentencep,q; sentence=(Sentence)malloc(sizeof(S)); q=sentence; q->next=NULL; printf("请输入待编码的字符串: \n"); fflush(stdin); while(scanf("%c",&c)! =EOF&&c! ='\n'){ for(i=1;i<=n;i++){ t=code[i]; if(c==t){ pp=HC[i]; break; } } for(i=0;pp[i]! ='\0';i++){ p=(Sentence)malloc(sizeof(S)); p->c=pp[i]; q->next=p; p->next=NULL; q=p; } } p=sentence->next; printf("\n编码后的语句: \n"); while(p! =NULL){ printf("%c",p->c); p=p->next; } printf("\n"); } voidDecoding(Sentence&sentence,char*&code,HuffmanCode&HC,Tree&root,intn){//解码 Treep,q; Sentencer=sentence->next; inti,j; charc,*t; root=(Tree)malloc(sizeof(TreeNode)); root->lchild=NULL; root->rchild=NULL; for(i=1;i<=n;i++){ t=HC[i]; q=root; for(j=0;j c=t[j]; if(q->lchild! =NULL){ if(q->lchild->code==c){ q=q->lchild; } elseif(q->rchild! =NULL){ q=q->rchild; } else{ p=(Tree)malloc(sizeof(TreeNode)); p->lchild=NULL; p->rchild=NULL; p->code=c; if(t[j+1]! ='\0') p->data='n'; else p->data=code[i]; q->rchild=p; q=p; } } else{ p=(Tree)malloc(sizeof(TreeNode)); p->lchild=NULL; p->rchild=NULL; p->code=c; if(t[j+1]! ='\0') p->data='n'; else p->data=code[i]; q->lchild=p; q=p; } } } q=root; printf("\n解码后的语句: \n"); while(r! =NULL){ c=r->c; if(q->lchild! =NULL){ if(q->lchild->code==c){ q=q->lchild; if(q->lchild==NULL){ printf("%c",q->data); q=root; } } else{ q=q->rchild; if(q->lchild==NULL){ printf("%c",q->data); q=root; } } } else{ printf("%c",q->data); q=root; } r=r->next; } printf("\n\n"); return; } intmain(void){//主函数 HuffmanTreeHT; HuffmanCodeHC; Treeroot; int*w,n,i; char*code; printf("\t\t设字符集为26个英文字母,其出现频度如下表所示: \n"); printf("\t\t******************************************\n"); printf("\t\t字符|空格|a|b|c|d|e|f|g|h|\n"); printf("\t\t频度|186|64|13|22|32|103|21|15|47|\n");printf("\n"); printf("\t\t字符|i|j|k|l|m|n|o|p|q|\n"); printf("\t\t频度|57|1|5|32|20|57|63|15|1|\n");printf("\n"); printf("\t\t字符|r|s|t|u|v|w|x|y|z|\n"); printf("\t\t频度|48|51|80|23|8|18|1|16|1|\n"); printf("\t\t******************************************\n"); printf("请输入字符集大小n(整型): \n"); scanf(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈弗曼 编码 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)