数据结构试验报告--哈夫曼编译器_第1页
数据结构试验报告--哈夫曼编译器_第2页
数据结构试验报告--哈夫曼编译器_第3页
数据结构试验报告--哈夫曼编译器_第4页
数据结构试验报告--哈夫曼编译器_第5页
免费预览已结束,剩余13页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、数据结构实验报告题目:专业:班级:组别:组长:完成日期:年月日评分依据及结果态度(A-D)规范性(A-D)完成度(A-D)总评(A-D)评语代码分工情况姓名工作内容实验报告分工情况姓名耿丽丽工作内容需求分析概要分析一、需求分析利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。本次设计要求对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。系统应具有如下的几个功能:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable)利用已经建好的哈夫曼树进行编码,

2、并将每个字符的编码输出。3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。5、打印(Print):以直观的方式打印哈夫曼树.二、概要设计本程序的数据类型定义为typedefstructintweight;intparent,lchild,rchild;HTNode,*HuffmanTree;typedefchar*HuffmanCode;/把字母和相应的权值放在一起typedefstruct(charch;intwht;WeNu;所实现的功能函数如下/统计叶子结点

3、的权值voidCountWeight(char*str);/选择parent为0,且weight最小的两个节点序号为s1,s2voidSelect(HuffmanTreeHT,intlen,int&s1,int&s2);/构造哈夫曼树HTvoidCreatHuffmanTree(HuffmanTree&HT,intn)/从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中voidCreatHuffmanCode(HuffmanTreeHT,HuffmanCode&HC,intn)/输出编码voidShowCode(HuffmanTreeHT,HuffmanC

4、odeHC,intn)/输出哈夫曼voidShowHuffman(HuffmanTreeHT,HuffmanCodeHC,char*str)/输出字符串voidShowStr(char*str)/选择解码方式voidDeCoding();/主函数voidmain();主要结构如图所示三、详细设计1.统计字符频度自然语言描述:(1)取出字符串中的一个字符(2)遍历所有初始化的哈夫曼树结点(3)如果结点中有记录代表的字符且字符等于取出的字符,说明该字符的叶子存在,则将该结点的权值加1(4)如果所有结点记录的字符均没有与取出的字符一致,说明该字符的叶子不存在,则将结点的字符记为取出字符,并将权重设为

5、1(5)重复以上步骤,直至字符串中所有字符全部遍历伪代码描述:1. for(inti=0;i<length;i+)1.1 for(intj=0;j<length;j+)1.1.1if(WordStri=HuffTreej.word)/若字符已被统计,则增加权值即可1.1.1.1 权重+;1.1.1.2 break;1.1.2elseif(!HuffTreej.word)/否则需要一个新结点储存这个字符1.1.2.1 HuffTreej.word=WordStri;1.1.2.3 HuffTreej.weight=1;1.1.2.4 break;时间复杂度O(N2),空间复杂度S(0

6、)2 .构造哈夫曼树:自然语言描述:(1)选出权值最小的两个结点,其权值和作为其根结点的权值,最小的结点作为左子树;(2)次小的做为右子树,不断将两棵子树合升为一棵树。重复及上述过程,直至所有结点全被遍历完。3 .为每个叶子结点编码自然语言描述:(1)初始化一个字符数组Code暂存每个叶子节点的编码;(2)前序遍历哈夫曼树;(3)若结点左右子树都为-1,则将Code复制到编码的Code串,准备返回上一层,编码相位少一位,Code长度-1,返回;(4)否则按照从左到右的顺序前序遍历根结点的所有子树;(5)若访问左子树,则进入下一层,编码相位多一位,Code长度加1并将最后一位赋值为0,访问右子树

7、,进入下一层,Code长度加1并将最后一位赋值为0。4、编码自然语言描述:(1)定义字符串CodeStr储存编码(2)遍历输入字符串的每一个字符(3)对每一个字符,将其与HuffTree前n个叶子节点的word逐个比较,相同则将该节点的编码串Code连接到CodeStr。5、译码自然语言描述:(1)从编码串CodeStr的第一个字符串开始于HuffTree的第一个节点的编码域第一个字符比较(2)相等则比较后面的字符(3)否则,从CodeStr第一个字符与HuffTree第二个结点的编码比较(4)重复上述过程,将CodeStr中的所有字符比较完毕四、调试分析1 .在写程序与调试的过程中,发现自己

8、对于函数的调用与参数的传递的方面还是存在很多问题,从参数的类型等等方面都出现了很多问题。2 .关于这个程序的要求比较复杂,刚开始做的时候没有任何思路,最后分模块一点点的进行。3 .递归函数中的参数传递在给每个字符编码时,由于编码是从根结点开始,所以选用与前序遍历相似的递归遍历形式。其中需要一个字符型数组来记录路径和编码,由于递归一次才有一位编码,所以这个数组也要随着递归函数的进行而不断修改。开始时我们没有用指针最为参数而是直接将数组作为参数.结果发现每次调用递归函数时数组都是空。原来我用的是值传递,数组就算修改了也无法返回。这提醒了我们之后运用递归函数时如果需要某个变量随函数递归而修改时应该使

9、用地址传递而并非值传递。心得体会:哈夫曼树又称做最优叉树,它是n个带权的叶子结点构成的所有二叉树中,带权路径长度WPLt小的二叉树。在n个带权的叶子结点所构成的二叉树中,满二叉树或完全二叉树不一定是最优二叉树。权值越大的结点离树根越近的二叉树才是最优叉树。哈夫曼树是根据字符出现的概率来构造平均长度最短的编码。它是-种变长的编码。在编码中,若各码字长度亚格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。哈夫曼树的应用非常广泛,在通信中,采用0.1的不同排列来表示不同的字符,而哈夫曼树在数据编码中的应用,若每个字符出现的频率相同,则可以采用等长的二进制编码,若频率不同,则可以

10、采用不等长的二进编码,频率较大的采用位数较少的编码,频率较小的字符采用位数较多的编码,这样可以使字符的整体编码长度最小,哈夫曼编码就是一种不等长的二进制编码,且哈夫曼树是一种最优二叉树,它的编码也是-种最优编码,在哈夫曼树中,规定往左编码为0,往右编码为1,则得到叶子结点编码为从根结点到叶子结点中所有路径中0和1的顺序排列。下一步的改进程序中多次使用了遍历数组或对数据进行逐个比对,循环的次数可以通过计算再减少,提高时间效率。五、用户守则请使用Windows系统来打开,平台为VisualStudid要注意文本的打开方式和设置六、测试结果(及截图)七、附录(源代码)头文件#define_CRT_S

11、ECURE_NO_WARNINGS#include<iostream>#include<stdio.h>#include<string.h>#include<cstring>usingnamespacestd;#defineNUM26typedefstructcharch;intwht;WeNu;把字母和相应的权值放在一起typedefstructintweight;intparent,lchild,rchild;HTNode,*HuffmanTree;typedefchar*HuffmanCode;源文件/#include"weigh

12、t.cpp"#include"Huffman.h"WeNuweightNUM+1;voidCountWeight(char*str)for(inti=1;i<=NUM;i+)charcha=(char)(i+96);出过错weighti.ch=cha;/简短代码/*switch(i)case 1:weight1.ch='a'break;case 2:weight2.ch='b'break;case 3:weight3.ch='c'break;case 4:weight4.ch='d'break;

13、case 5:weight5.ch='e'break;case 6:weight6.ch='f;break;case 7:weight7.ch='g'break;case 8:weight8.ch='h'break;case 9:weight9.ch='i'break;case 10:weight10.ch='j'break;case 11:weight11.ch='k'break;case 12:weight12.ch='l'break;case 13:weight13.c

14、h='m'break;case 14:weight14.ch='n'break;case 15:weight15.ch='o'break;case 16:weight16.ch='p'break;case 17:weight17.ch='q'break;case 18:weight18.ch='r'break;case 19:weight19.ch='s'break;case 20:weight20.ch='t'break;case 21:weight21.ch=&#

15、39;u'break;case 22:weight22.ch='v'break;case 23:weight23.ch='w'break;case 24:weight24.ch='x'break;case 25:weight25.ch='y'break;case 26:weight26.ch='z'break;default:cout<<"error!"<<endl;*/weighti.wht=0;intn=strlen(str);for(inti=0;i<

16、n;i+)charc=stri;weight(int)c)-96.wht+;/减短代码/switch(c)/case'a':/weight1.wht+;/break;/case'b':/weight2.wht+;/break;/case'c':/weight3.wht+;/break;/case'd':/weight4.wht+;/break;/case'e':/weight5.wht+;/break;/case'f':/weight6.wht+;/break;/case'g':/w

17、eight7.wht+;/break;/case'h':/weight8.wht+;/break;/case'i':/weight9.wht+;/break;/case'j':/weight10.wht+;/break;/case'k':/weight11.wht+;/break;/caseT:/weight12.wht+;/break;/case'm':/weight13.wht+;/break;/case'n':/weight14.wht+;/break;/case'o':/we

18、ight15.wht+;/break;/case'p':/weight16.wht+;/break;/case'q':/weight17.wht+;/break;/case'r':/weight18.wht+;/break;/case's':/weight19.wht+;/break;/case't':/weight20.wht+;/break;/case'u':/weight21.wht+;/break;/case'v':/weight22.wht+;/break;/case

19、9;w':/weight23.wht+;/break;/case'x':/weight24.wht+;/break;/case'y':/weight25.wht+;/break;/case'z':/weight26.wht+;/break;/default:/cout<<"error!"<<endl;/*/voidSelect(HuffmanTreeHT,intlen,int&s1,int&s2)inti,min1=0x3f3f3f3f,min2=0x3f3f3f3f;/先赋予最

20、大值for(i=1;i<=len;i+)if(HTi.weight<min1&&HTi.parent=0)min1=HTi.weight;s1=i;inttemp=HTs1.weight;/将原值存放起来,然后先赋予最大值,防止s1被重复选择HTs1.weight=0x3f3f3f3f;for(i=1;i<=len;i+)if(HTi.weight<min2&&HTi.parent=0)min2=HTi.weight;s2=i;HTs1.weight=temp;/恢复原来的值voidCreatHuffmanTree(HuffmanTree

21、&HT,intn)构造赫夫曼树HTintm,s1,s2,i;if(n<=1)return;m=2*n-1;HT=newHTNodem+1;/0号单元未用,所以需要动态分配m+1个单元,HTm表示根结点for(i=1;i<=m;+i)将1m号单元中的双亲、左孩子,右孩子的下标都初始化为0HTi.parent=0;HTi.lchild=-(96+i);HTi.rchild=-(96+i);/a的ASCII是97!/cout<<"请输入叶子结点的权值:n"for(i=1;i<=n;+i)输入前n个单元中叶子结点的权值HTi.weight=we

22、ighti.wht;/*初始化工作结束,下面开始创建赫夫曼树*/for(i=n+1;i<=m;+i)通过n-1次的选择、删除、合并来创建赫夫曼树Select(HT,i-1,s1,s2);/在HTk(1&k<i-1)中选择两个其双亲域为0且权值最小的结点,/并返回它们在HT中的序号s1和s2HTs1.parent=i;HTs2.parent=i;得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由。改为iHTi.lchild=s1;HTi.rchild=s2;/s1,s2分另”乍为i的左右孩子HTi.weight=HTs1.weight+HTs2.weight;/i的

23、权值为左右孩子权值之和/for/CreatHuffmanTreevoidCreatHuffmanCode(HuffmanTreeHT,HuffmanCode&HC,intn)从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中inti,start,c,f;HC=newchar*n+1;char*cd=newcharn;cdn-1='0'for(i=1;i<=n;+i)start=n-1;c=i;f=HTi.parent;while(f!=0)-start;if(HTf.lchild=c)cdstart='0'elsecdstart='1

24、'c=f;f=HTf.parent;HCi=newcharn-start;strcpy(HCi,&cdstart);deletecd;分配n个字符编码的头指针矢量/分配临时存放编码的动态数组空间/编码结束符/逐个字符求赫夫曼编码/start开始时指向最后,即编码结束符位置/f指向结点c的双亲结点从叶子结点开始向上回溯,直到根结点/回溯一次start向前指一个位置结点c是f的左孩子,则生成代码0结点c是f的右孩子,则生成代码1继续向上回溯求出第i个字符的编码/为第i个字符编码分配空间将求得的编码从临时空间cd复制到HC的当前行中/释放临时空间)voidShowCode(Huffm

25、anTreeHT,HuffmanCodeHC,intn)(for(inti=1;i<=n;i+)(cout<<weighti.ch<<"("<<HTi.weight<<")"<<"编码为"<<HCi<<"ttt"if(i%2=0)(printf("n");)voidShowHuffman(HuffmanTreeHT,HuffmanCodeHC,char*str)(inti=0;while(stri!=

26、9;0')(charc=stri;cout<<HC(int)c)-96;/简短代码/*switch(c)case'a':cout<<HC1;break;case'b':cout<<HC2;break;case'c':cout<<HC3;break;case'd':cout<<HC4;break;case'e':cout<<HC5;break;case'f':cout<<HC6;break;case'g

27、':cout<<HC7;break;case'h':cout<<HC8;break;case'i':cout<<HC9;break;case'j':cout<<HC10;break;case'k':cout<<HC11;break;case'l':cout<<HC12;break;case'm':cout<<HC13;break;case'n':cout<<HC14;break;c

28、ase'o':cout<<HC15;break;case'p':cout<<HC16;break;case'q':cout<<HC17;break;case'r':cout<<HC18;break;case's':cout<<HC19;break;case't':cout<<HC20;break;case'u':cout<<HC21;break;case'v':cout<<HC22;break;case'w':cout<<HC23;break;case'

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论