ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:156KB ,
资源ID:20765229      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20765229.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(实验三哈夫曼树实验报告Word文件下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

实验三哈夫曼树实验报告Word文件下载.docx

1、(1)二叉树template class BiTreepublic: BiTree(); /构造函数,其前序序列由键盘输入 BiTree(void); /析构函数 BiNode* Getroot(); /获得指向根结点的指针protected: *root; /指向根结点的头指针;/声明类BiTree及定义结构BiNodeData: 二叉树是由一个根结点和两棵互不相交的左右子树构成。 二叉树中的结点具有相同数据类型及层次关系。示意图: root lchild parent rchild (2)静态三叉链表struct HNode /哈夫曼树的静态三叉链表 unsigned int weight

2、; /结点权值 unsigned int parent; /双亲指针 unsigned int Lchild; /左孩子指针 unsigned int Rchild; /右孩子指针(3) 编码表的节点结构struct HCode /字符及其编码结构 char data; char code100;2.2关键算法分析一:关键算法 (一)初始化函数 void Huffman:Init(int a,int n)(1)算法自然语言1.创建一个长度为2*n -1的三叉链表2.将存储字符及其权值的链表中的字符逐个写入三叉链表的前n个结点的data域,并将对应结点的孩子域和双亲域赋为空3.从三叉链表的第n个

3、结点开始,i=n3.1从存储字符及其权值的链表中取出两个权值最小的结点x,y,记录其下标x,y。3.2将下标为x和y的哈夫曼树的结点的双亲设置为第i个结点3.3将下标为x的结点设置为i结点的左孩子,将下标为y的结点设置为i结点的右孩子,i结点的权值为x结点的权值加上y结点的权值,i结点的双亲设置为空4. 根据哈夫曼树创建编码表(2)源代码void Huffman:Init(int a,int n) /创建哈夫曼树 /二叉树只有度为和度为的结点时,总结点数为(n-1)个 HTree=new HNode2*n-1; /根据权重数组a1n初始化哈夫曼树 int i,x,y; for(i=0;in;i

4、+) /n个叶子结点 HTreei.weight=ai; HTreei.Lchild=-1; HTreei.Rchild=-1; HTreei.parent=-1; for(int i=n;2*n-1;i+) /开始建哈夫曼树,从底层向顶层搭建 SelectMin(HTree,i,x,y); /从-(i-1)中选出两个权值最小的结点 HTreex.parent=i; HTreey.parent=i; /左右孩子权值相加为父结点的权值 HTreei.weight=HTreex.weight+HTreey.weight; HTreei.Lchild=x; HTreei.Rchild=y;(3)时间

5、复杂度在选取两个权值最小的结点的函数中要遍历链表,时间复杂度为O(n),故该函数的时间复杂度为O(n2)(二)统计字符出现频度的代码用cin.getline()函数获取一段字符串。同时设置一个权值数组weight,以及暂时统计和存放权值的数组s。用 strlen()函数获取未编码时的字符串长度。从字符串的起始位置进行权值统计,即获得stri每个字符的AS编码,并在s(int)stri数组中进行+1统计,为字符出现一次。 i进行自加,统计下面字符出现的频度,在相应的数组元素中进行+1统计。继续循环,直到字符串结束。(2)源代码(在main()函数中实现)int i,j=0,v; int s200

6、=0; int weightM; /权值数组 cout请输入一段字符串,按回车键结束:endl; cin.getline(str,1000,n); /由用户输入一段字符串 Len1=strlen(str); /得到未编码时的字符串长度stri!=0;i+) /统计每个字符的权值 s(int)stri+; /(int)stri为每个字符的AS编码200;i+) if(si!=0) /如果权值不为 cj=i; /AS编码为i的字符写入字符数组c weightj=si; /权值s数组赋给权值weight数组 j+; n=j; /叶子结点个数 for(v=0;vv+) /循环输出字符权值cv的权值为:

7、weightvhTreei2.weight) /i1指向最小的 j=i2; i2=i1; i1=j;i+) /开始找最小的两个 if(hTreei.parent=-1&hTreei.weighthTreei1.weight) /如果之后的叶子结点权值小于前两个,那么进行交换 /把i1赋给i2 else if(hTreei.parent=-1&hTreei2.weight) /始终保证i2权值大于i1若输入的字符串长度为n,则时间复杂度为O(n)(四)创建编码表1.生成一个编码表2.从终端结点开始,如果此结点是其父结点的左孩子,则标“0”;如果是其父结点的右孩子,则标“1”。3.将父结点赋给孩子

8、结点,并将新的孩子结点的父结点作为当前父结点,重复2操作。4.继续循环,直到根结点,即不满足循环条件时,将编码表的最后一位置0.5.将编码字符逆置。将编码串的最后一位置换成新编码串的第一位,倒数第二位置换成新编码串的第二位,直到置换完毕。6.将新的编码串重新赋给编码表。7.输出字符的哈夫曼编码。8.循环将字符编码后的长度赋给Len3数组。CreateTable(char data,int n) HCodeTable=new HCoden; /生成编码表 for(int i=0; HCodeTablei.data=datai; int child=i; int parent=HTreei.par

9、ent; int k=0; /从终端结点开始编码,代表每个编码串的长度 while(parent!=-1) if(child=HTreeparent.Lchild) HCodeTablei.codek=0 /左孩子标“0” else1 /右孩子标“1” k+; child=parent; /向上追溯 parent=HTreechild.parent; /当编码到根结点时循环结束,编码串最后一位置表结束 /将编码字符逆置 char codeM; int u; for(u=0;uk;u+) codeu=HCodeTablei.codek-u-1;/上述编码串的最后一位变成新的编码表中编码串的第一位

10、 HCodeTablei.codeu=codeu; /将新的编码串重新赋给编码表ci的哈夫曼编码为:HCodeTablei.code Len3i=k; /每个字符编码后的长度若输入的字符串长度为n,则时间复杂度为O(n)。(五)编码算法1.从字符串的起始位置开始,将每个字符与编码表中的字符进行比对。2.当两字符相等时,输出编码表中字符对应的编码。3.将此字符编码的长度加到Len2中,循环结束后,Len2的数值为字符串编码后的总长度。Encoding(int n) /编码endl输入的字符串转化为哈夫曼编码为: for (int i=0;i+) /只要字符串不结束就执行循环 for(int j=

11、0;jj+) if(stri=HCodeTablej.data) /如果字符串中的字符与编码表中的字符相等HCodeTablej.code; /输出编码表中字符对应的编码 Len2+=Len3j; /求编码后的字符总的编码长度,为了求压缩比 设待编码字符串长度为n,编码表中字符个数为m,则复杂度为O(n*m)。(六)解码算法1.从根节点开始,如果编码串为0,则下溯到此结点的左孩子结点;如果编码串为1,则下溯到此结点的右孩子结点。2.执行循环,直到不满足while循环条件,即追溯到叶子结点。输出叶子结点的字符。Decoding(char* p) /p为编码串解码后的字符串为: char* q=0

12、; while(*p!) int parent=2*n-1-1; /根结点在哈夫曼树中的下标 while(HTreeparent.Lchild!=-1) /如果不是叶子结点就执行循环 if(*p=) parent=HTreeparent.Lchild; else if(*p= parent=HTreeparent.Rchild; p+;HCodeTableparent.data; /输出叶子结点的字符(七)计算压缩比函数1.获得编码前字符串的长度,即其占用的字节数(float类型)。2.获得编码后的字符串的长度,将其除以8,得到其占用的字节数(float类型)。3.压缩比将两个相除。Calcu

13、late(int x, int y) /编码前后的压缩比 编码前字符串长度为:x Byte /编码前以字节存储编码后字符串的大小为:y bit /编码后以位存储压缩比为:(float)(y/8)/(float)x)*100% /计算压缩比 (3)时间复杂度时间复杂度为O(1)。2.3其他 1.由于题目要求能输入任意长的字符串,所以本程序采用了string变量来记录输入的字符串,并采用string类的类成员函数来完成各项任务 2.统计权值代码和将编码串逆置的代码都没有单独定义函数。其中统计权值代码放到了主程序中,将编码串逆置代码放到了CreateTable()函数中。 3.未能将哈夫曼树直观打印

14、出来。3、程序运行结果(1)程序流程图(2)测试条件由用户任意输入一段字符,进行编码解码等操作。(3)运行结果:(4)说明:各函数运行正常,没有出现bug。四、总结1、调试时出现的问题及解决方法在给每个字符编码时,由于编码是从根结点开始,所以选用与前序遍历相似的递归遍历形式。其中需要一个字符型数组来记录路径和编码,由于递归一次才有一位编码,所以这个数组也要随着递归的进行而不断修改。开始时我没有用引用作为参数而是直接将数组作为参数,结果发现每次调用递归时数组都是空。原来我用的是值传递,数组就算修改了也无法返回。这提醒了我之后运用递归时如果需要某个变量随函数递归而修改时应该使用地址传递而非值传递。

15、2、心得体会这是第三次实验编程,相比前两次实验的相对生疏来说,这次对于基本语句的运用差不多能熟练掌握。但是还是出现了不少的问题,比如在基本代码以及主程序敲定完成以后,编译并没有出现错误,但是一运行,编码就输出为无限循环,反复调试也找不出关键所在,一直坐在电脑前呆呆地看了代码两个小时,还是一无所获;后来隔一段时间之后自己又转回来重新看代码,才恍然大悟,原来是循环条件写错,编码逆置和逆置后的代码重新赋给数组没有做到两层分别循环,导致整个语句块未能正常调用。修改之后一切运行正常。我也明白了,如果一直盯着代码看,多数情况是什么也看不出来的,因为你脑袋里充斥的都是那短短几句代码,越想反而越糊涂;如果过一阵自己头脑清醒了再去想问题说不定会有新发现。这次实验,总结说来,让我更好地掌握了哈夫曼树的创建过程,了解了一种不等长编码的方法,用设断点调试的方法更加熟练,同时熟悉了STL中string类型的用法,对C+更加熟悉。3.下一步改进可以直观输出哈夫曼树,但是打印树需要考虑到结点所在的层次和需要打印空格的个数,难度有点大。主函数中用户交互界面做得还不是很好,之后的改进可以是用case条件语句,由用户决定输出权值、编码、解码等函数执行结果的次序。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1