数据结构赫夫曼编译码器.docx
- 文档编号:29696026
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:24
- 大小:214.33KB
数据结构赫夫曼编译码器.docx
《数据结构赫夫曼编译码器.docx》由会员分享,可在线阅读,更多相关《数据结构赫夫曼编译码器.docx(24页珍藏版)》请在冰豆网上搜索。
数据结构赫夫曼编译码器
院系:
计算机科学学院
专业:
计算机科学与技术
年级:
2008
课程名称:
学号:
姓名:
指导教师:
2010年6月2日
年级
2008
班号
01
学号
专业
计算机科学与计术
姓名
实验名称
哈弗曼编/译码器
实验
类型
设计型
综合型
创新型
√
实
验
目
的
或
要
求
一个完整的系统应具有以下功能:
(1)I:
初始化。
从终端读入字符集大小n,n个字符和n个权值,建立哈弗曼树,并将它存于文件hfmTree.
(2)E:
编码。
利用已建好的树,对文件ToBeTran中的正文进行编码,然后将结果存入CodeFile中。
(3)D:
译码。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:
印代码文件。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时,将此字符形式的哈夫曼树写入文件TreePin中。
(5)T:
印哈弗曼树。
将哈夫曼树以直观的方式显示在终端上,同时将此树写入文件TreePrint中。
实
验
原
理
(
算
法
流
程
)
一.算法流程
①建立HuffmanTree
voidHaffmanTree:
:
Haffman(intweight[],HaffmanTreeHT[])
a.查找哈夫曼链表中两个权值最小的节点:
b.创建哈弗曼树
②哈夫曼编码和译码
voidHaffmanTree:
:
HaffmanCode(HaffmanTreehaffTree[],HaffmanTreeHaffCode[],charch[],strings)
⑦解码函数:
DeCoding(charcode[],HFMTreeHT,charstr[],char[])s
二.哈夫曼编码的算法
(1)字符集编码的存储结构及其算法描述
typedefstruct{
charch;//存储字符
charbits[n+1];//存放编码位串
}CodeNode;
typedefCodeNodeHuffmanCode[n];
voidCharSetHuffmanEncoding(HuffmanTreeT,HuffmanCodeH)
{//根据哈夫曼树T求哈夫曼编码表H
intc,p,i;//c和p分别指示T中孩子和双亲的位置
charcd[n+1];//临时存放编码
intstart;//指示编码在cd中的起始位置
cd[n]='\0';//编码结束符
for(i=0,i H[i].ch=getchar();//读入叶子T[i]对应的字符 start=n;//编码起始位置的初值 c=i;//从叶子T[i]开始上溯 while((p=T[c].parent)>=0){//直至上溯到T[c]是树根为止 //若T[c]是T[p]的左孩子,则生成代码0;否则生成代码1 cd[--start]=(T[p).1child==C)? '0': '1'; c=p;//继续上溯 } strcpy(H[i].bits,&cd[start]);//复制编码位串 }//endfor }//CharSetHuffmanEncoding 三.文件的编码和解码 有了字符集的哈夫曼编码表之后,对数据文件的编码过程是: 依次读人文件中的字符c,在哈夫曼编码表H中找到此字符,若 H[i].ch=c,则将字符c转换为H[i].bits中存放的编码串。 对压缩后的数据文件进行解码则必须借助于哈夫曼树T,其过程是: 依次读人文件的二进制码,从哈夫曼树的根结点(即T[m-1])出发,若当前读人0,则走向左孩子,否则走向右孩子。 一旦到达某一叶子T[i]时便译出相应的字符H[i].ch。 然后重新从根出发继续译码,直至文件结束。 实 验 结 果 分 析 及 心 得 体 会 测试数据: 利用教科书例6-2中的数据调试程序,并设第1到第8个字符为a,b,c,d,e,f,g,h。 运行结果图: 运行结果分析: 通过调试发现该程序满足哈弗曼树,哈弗曼编码与译码的基本要求,满足课程设计任务的基本功能与要求。 在以后的学习中希望能将程序进一步优化,思想更简单明了,使程序变得更完善。 心得体会 通过一周的编程设计使我对哈夫曼树以及哈夫曼编码有了更深的认识和理解,也使我更加明白哈夫曼编码译码在信息技术中的重要性和地位。 通过对数据结构和课程设计的学习,使我们能够以问题求解方法、程序设计方法以及一些典型的数据结构算法为研究对象,分析数据对象的特征,掌握数据组织的方法和在计算机中的表示方法,为数据选择适当的逻辑结构、存储结构以及相应的处理算法,使我们初步掌握了算法的时间、空间复杂度的分析技巧,并逐步培养了良好的程序设计风格以及进行复杂程序设计的技能。 数据结构一科的重要内容和主要难点是让我们理解、习惯和熟悉算法构造性思维方法。 在设计过程中,我深刻认识到算法的逻辑性对程序的重要影响,算法的准确度对程序运行结果的重要影响,构建最小代价生成树时,一个细微的循环控量的错误都能影响到程序的正确性,而所有的代码机制都是为一个目标的实现而运作的,所以,细致是实现算法和程序准确性必不可少的。 同时,对于编程者而言,思路清晰是相当重要的。 在适当的时候和同学一起交流探讨是一个十分好的学习机会。 请教老师也很重要,能有效地节约时间。 成 绩 评 定 教师签名: 年月日 (注: 源码附后) #include #include #include #include #include constintUINT_MAX=1000; typedefstruct { intweight;//权值 intparent,lchild,rchild; }HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树 typedefchar**HuffmanCode;//动态分配数组存储赫夫曼编码表 //-----------全局变量----------------------- HuffmanTreeHT;//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC. HuffmanCodeHC; int*w,n,i,j; char*z; intflag=0; intnumb=0; //-----------------求赫夫曼编码----------------------- intmin(HuffmanTreet,inti) {//函数voidselect()调用 intj,flag; intk=UINT_MAX;//取k为不小于可能的值 for(j=1;j<=i;j++) if(t[j].weight k=t[j].weight,flag=j; t[flag].parent=1; returnflag; } //--------------------slect函数---------------------- voidselect(HuffmanTreet,inti,int&s1,int&s2) {//s1为最小的两个值中序号小的那个 intj; s1=min(t,i); s2=min(t,i); if(s1>s2) {j=s1; s1=s2; s2=j; } } //--------------算法6.12-------------------------- voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,intn) {//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC intm,i,s1,s2,start; intc,f; HuffmanTreep; char*cd; if(n<=1) return;//检测结点数是否可以构成树 m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未用 for(p=HT+1,i=1;i<=n;++i,++p,++w)//初始化 { p->weight=*w; p->parent=0; p->lchild=0; p->rchild=0; } for(;i<=m;++i,++p) p->parent=0; for(i=n+1;i<=m;++i)//建赫夫曼树 {//在HT[1...i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2. select(HT,i-1,s1,s2); HT[s1].parent=HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } //---从叶子到根逆向求每个字符的赫夫曼编码--- HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量([0]不用) 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));//为第i个字符编码分配空间 strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC } free(cd);//释放工作空间 } //--------------初始化赫夫曼链表--------------------------------- voidInitialization() { flag=1; intnum; intnum2; cout<<"下面初始化赫夫曼链表"< "; cin>>num; n=num; w=(int*)malloc(n*sizeof(int)); z=(char*)malloc(n*sizeof(char)); cout<<"\n请依次输入"< 必须以回车结束: "< charbase[2]; for(i=0;i { cout<<"第"< "< gets(base); *(z+i)=*base; } for(i=0;i<=n-1;i++) { cout< } cout<<"\n请依次输入"< 必须以回车结束): "< for(i=0;i<=n-1;i++) { cout< "; cin>>num2; *(w+i)=num2; } HuffmanCoding(HT,HC,w,n);//开始构造对应的赫夫曼树及这n个字符的赫夫曼编码 //------------------------打印编码------------------------------------------- cout<<"字符对应的编码为: "< for(i=1;i<=n;i++) { //cout<<"字符"<<*(z+i-1)<<"的编码"; puts(HC[i]); } //--------------------------将赫夫曼编码写入文件------------------------ cout<<"下面将赫夫曼编码写入文件"< FILE*htmTree; charr[]={'','\0'}; if((htmTree=fopen("htmTree.txt","w"))==NULL) { cout<<"cannotopenfile"< return; } fputs(z,htmTree); for(i=0;i { fprintf(htmTree,"%6d",*(w+i)); fputs(r,htmTree); } for(i=1;i<=n;i++) { fputs(HC[i],htmTree); fputs(r,htmTree); } fclose(htmTree); cout<<"已将字符与对应编码写入根目录下文件htmTree.txt中"< } //---------------------获取报文并写入文件--------------------------------- voidInputCode() { //cout<<"请输入你想要编码的字符"< FILE*tobetran; charstr[100]; if((tobetran=fopen("tobetran.txt","w"))==NULL) { cout<<"不能打开文件"< return; } cout<<"请输入你想要编码的字符"< gets(str); fputs(str,tobetran); cout<<"获取报文成功"< fclose(tobetran); } //---------------------编码函数--------------------------------- voidEncoding() { cout<<"下面对目录下文件tobetran.txt中的字符进行编码"< FILE*tobetran,*codefile; if((tobetran=fopen("tobetran.txt","rb"))==NULL) { cout<<"不能打开文件"< } if((codefile=fopen("codefile.txt","wb"))==NULL) { cout<<"不能打开文件"< } char*tran; i=99; tran=(char*)malloc(100*sizeof(char)); while(i==99) { if(fgets(tran,100,tobetran)==NULL) { cout<<"不能打开文件"< break; } for(i=0;*(tran+i)! ='\0';i++) { for(j=0;j<=n;j++)//编码,找到后写入文件"codefile.txt"中 { if(*(z+j-1)==*(tran+i)) { fputs(HC[j],codefile); if(j>n) { cout<<"字符错误,无法编码! "< break; } } } } } cout<<"编码工作完成"< fclose(tobetran); fclose(codefile); free(tran); } //-----------------译码函数--------------------------------- voidDecoding() { cout<<"下面对根目录下文件codefile.txt中的字符进行译码"< FILE*codef,*txtfile; if((txtfile=fopen("Textfile.txt","w"))==NULL) { cout<<"不能打开文件"< } //txtfile=fopen("Textfile.txt","w"); if((codef=fopen("codefile.txt","r"))==NULL) { cout<<"不能打开文件"< } //codef=fopen("codefile.txt","r"); char*work,*work2,i2; inti4=0,i,i3; unsignedlonglength=10000; work=(char*)malloc(length*sizeof(char)); fgets(work,length,codef); work2=(char*)malloc(length*sizeof(char)); i3=2*n-1; for(i=0;*(work+i)! ='\0';i++) { i2=*(work+i); if(HT[i3].lchild==0) { *(work2+i4)=*(z+i3-1); i4++; i3=2*n-1; i--; } elseif(i2=='0')i3=HT[i3].lchild; elseif(i2=='1')i3=HT[i3].rchild; } *(work2+i4)='\0';//译码结束符 fputs(work2,txtfile); cout<<"译码完成"< free(work); free(work2); fclose(txtfile); fclose(codef); } //-----------------------打印编码的函数---------------------- voidCode_printing() { cout<<"下面打印根目录下文件CodePrin.txt中编码字符"< FILE*CodePrin,*codefile; if((CodePrin=fopen("CodePrin.txt","w"))==NULL) { cout<<"不能打开文件"< return; } if((codefile=fopen("codefile.txt","r"))==NULL) { cout<<"不能打开文件"< return; } char*work3; work3=(char*)malloc(51*sizeof(char)); do { if(fgets(work3,51,codefile)==NULL) { cout<<"不能读取文件"< break; } fputs(work3,CodePrin); puts(work3); }while(strlen(work3)==50); free(work3); /*intiNum=2,num=2; while((num=fscanf(codefile,"%d",iNum))! =NULL) { printf("%d",iNum); fprintf(CodePrin,"%d",iNum); } */ cout<<"打印工作结束"< fclose(CodePrin); fclose(codefile); } //------------------------打印赫夫曼树的函数----------------------- voidcoprint(HuffmanTreestart,HuffmanTreeHT) { if(start! =HT) { FILE*TreePrint; if((TreePrint=fopen("TreePrint.txt","a"))==NULL) {cout<<"创建文件失败"< return; } numb++;//该变量为已被声明为全局变量 coprint(HT+start->rchild,HT); cout< fprintf(TreePrint,"%d\n",start->weight); coprint(HT+start->lchild,HT); numb--; fclose(TreePrint); } } voidTree_printing(HuffmanTreeHT,intw) { HuffmanTreep; p=HT+w; cout<<"下面打印赫夫曼树"< coprint(p,HT); cout<<"打印工作结束"< } //------------------------主函数------------------------------------ voidmain() { charchoice; while(choice! ='q') {cout<<"\n******************************"< cout<<"欢迎使用赫夫曼编码解码系统"< cout<<"******************************"< cout<<" (1)要初始化赫夫曼链表请输入'i'"< cout<<" (2)输入要编码的字符'w'"< cout<<"(3)要编码请输入'e'"< cout<<"(4)要译码请输入'd'"< cout<<"(5)要打印编码请输入'p'"< cout<<"(6)要打印赫夫曼树请输入't'"< cout<<"(7)要离开请输入
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 赫夫曼编 译码器