




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 目 录一、实验内容2二、实验说明2三、结构体定义和程序结构的说明31.结构体定义的说明33四、程序设计的根本思想、局部源代码及注释34.判断结点是否已经被使用过上机报告-构造一个哈夫曼树姓名 赵颖 学号2021114121 专业 信息与计算科学一、 实验内容根据输入的n个带权结点,构造出哈夫曼树,并且把构造结果输出到屏幕。二、实验说明哈夫曼数,也称最优二叉树,是指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树。设二叉树具有n个带权值的叶结点,那么从根结点到各个叶结点的路径长度与相应结点权值的乘积之和叫做二叉树的带权路径长度WPL,记作: WPL=。在给定一组具有确定权值的叶
2、结点,可以构造出不同的带权二叉树。根据哈夫曼树的定义,一棵二叉树要使其WPL值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。 在传送电文时,我们总是希望传送时间尽可能短,这就要求电文代码尽可能短。如果在编码时考虑字符出现的频率,让出现频率高的字符采用尽可能短的编码,出现频率低的字符采用稍长的编码,构造一种不等长编码,那么电文的代码就可能更短。并且在建立不等长编码时,必须使任何一个字符的编码都不是另一个字符编码的前缀,以防止反译成原文时,编码出现多义性。在哈夫曼编码树中,树的带权路径长度的含义是各个字符的码长与其出现次数的乘积之和,也就是电文的代码总长,所以采用哈夫曼
3、树构造的编码是一种能使电文代码总长最短的不等长编码。采用哈夫曼树进行编码,也不会产生上述二义性问题。因为,在哈夫曼树中,每个字符结点都是叶结点,它们不可能在根结点到其它字符结点的路径上,所以一个字符的哈夫曼编码不可能是另一个字符的哈夫曼编码的前缀,从而保证了译码的非二义性。 三、结构体定义和程序结构的说明1、结构体定义的说明哈夫曼树重点在于如何排列权值大小不同的结点的顺序,所以定义结构体如下:typedef structint weight; /*weight存储结点的权值*/int parent;int lchild;int rchild; /*分别保存父亲、左孩子、右孩子结点*/HTNod
4、e,*HuffmanTree;而另一个重点在于将两个权值为最小的结点分别作为左、右子树,所以定义结构体如下:typedef structunsigned int s1;unsigned int s2; /*分别存储最小和次小的结点*/MinCode;2、程序结构的说明程序主要由以下几局部组成:结构体 struct HTNode,*Huffmantree结构体 struct MinCode函数 Select 用以选择结点中权值最小的两个结点函数 CreateTree 将选出来的结点按规律逐步建成哈夫曼树 函数 main 主函数四、程序设计的根本思想、局部源代码及注释根据哈夫曼树的定义,一棵二叉树
5、要使其WPL值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。因此,构造哈夫曼树有此种方法:1、由给定的n个权值W1,W2,Wn构造n棵只有一个叶结点的二叉树,从而得到一个二叉树的集合FT1,T2,Tn;2、在F中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和;3、在集合F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树参加到集合F中;4、重复23两步,当F中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。所以,构造哈夫曼树主要由两个步骤组成:一是选择所有结点中权值最小的两个结点
6、,二是将这些结点参加到二叉树中,构建成哈夫曼树。1、 在所有结点中选出权值最小的两个结点。、选择权值最小的两个结点并不难,难在如何判断该结点是否已经使用过,假设不能正确判断前面构造的哈夫曼树中是否使用过该结点,可能造成结点重复出现在树中,出现错误。根据哈夫曼树构造的特点,当两个结点的权值为最小时就将做为新的二叉树的左右子树,而它们的权值之和为它们的根结点,所以可以通过判断该结点是否有父亲结点来判断它是否被使用过。if(HTi.parent=0) /*没有父亲结点说明该 结点还未被使用过*/ min=HTi.weight; /*给min赋初始值*/ s1=i; /*将结点的编号赋给s1*/ br
7、eak; tempi=i+; /*i确定下一个结点的编号*/、然后利用数字排序的方法,对符合要求的结点进行判断,当存在权值更小的结点是,将该结点的内容赋给min和s1.for(;i<=n;i+) if(HTi.weight<min&&HTi.parent=0) /*当结点i未被使用并且权min=HTi.weight; 值小于min时,将权值赋s1=i; 给min,编号赋给s1*/ 、采用同样的方法可以选择出另一个权值为最小的结点。for(i=tempi;i<=n;i+) if(HTi.parent=0&&i!=s1) secmin=HTi.we
8、ight; s2=i; break; for(i=1;i<=n;i+) if(HTi.weight<secmin&&i!=s1&&HTi.parent=0) secmin=HTi.weight; s2=i; 、再通过判断结点s1和结点s2的权值的大小来确定权值为最小的结点和权值为第二小的结点,并将值保存再结构体中。if(s1>s2) temp=s1; s1=s2; s2=temp; code.s1=s1; code.s2=s2; return code;2、 将选择出来的结点一个个逐步构建成哈夫曼树。、哈夫曼树实现的功能就是将假设干个结点以最优
9、化的顺序排列出来,所以当结点数n=1时,不存在构建哈夫曼树的问题。因此,首先对可能出现的这种状况进行判断。if(n<=1) printf("Error:Code too small!"); 、因为哈夫曼树的叶子结点为n个,结点数为2*n-1个,所以可以直接定义构建的哈夫曼树的结点个数m。并对输入的结点和待构建的哈夫曼树上的结点进行初始化。m=2*n-1; /*定义哈夫曼树的结点个数*/HT=(HuffmanTree)malloc(m+1)*sizeof(HTNode); for(p=HT,i=0;i<=n;i+,p+,w+) /*0号单元未用*/ p->w
10、eight=*w; p->parent=0; /*给待处理的结点赋予权值,父 p->lchild=0; 亲、左孩子、右孩子均赋0值*/ p->rchild=0; for(;i<=m;i+,p+) p->weight=0; p->parent=0; /*对待构建的哈夫曼树 p->lchild=0; 的编码进行初始化*/ p->rchild=0; 、构建哈夫曼树,通过Select函数选择还未被使用的且权值为最小的两个结点,将其参加到树中。for(i=n+1;i<=m;i+) min=Select(HT,i-1); s1=min.s1; /*s1
11、、s2分别存权值最小 s2=min.s2; 的两个结点的编号*/HTs1.parent=i; HTs2.parent=i; HTi.lchild=s1; HTi.rchild=s2; HTi.weight=HTs1.weight+HTs2.weight; 、构建完成哈夫曼树后,为知道每个结点的具体编码,必须对哈夫曼树进行遍历,且必须从叶子结点向根结点逆序进行遍历。HC=(HuffmanCode)malloc(n+1)*sizeof(char *); cd=(char *)malloc(n*sizeof(char *); /*分配求编码的工作空间*/cdn-1='0' /*编码结
12、束符*/for(i=1;i<=n;i+) /*逐个字符求赫夫曼编码*/ start=n-1; /*编码结束符位置*/ for(c=i,f=HTi.parent;f!=0;c=f,f=HTf.parent) /*从叶子到根逆向求每个 if(HTf.lchild=c) 字符的赫夫曼编码*/ cd-start='0' /*左孩子赋0值*/ else cd-start='1' /*右孩子赋1值*/ 3、输出的设置 由于哈夫曼树的树形结构比拟难在计算机屏幕上实现,而又需要明确的表示出每个结点在树中的位置,所以对输出采取了以下两种样式。 、输出每个结点的父亲、左孩子、
13、右孩子结点的编号,从而确定每个结点的具体位置。由于在构建哈夫曼树的Create函数中已经完成了每个结点的父亲、左孩子、右孩子结点的赋值,所以只需要将这些值直接输出即可。printf("HT List:n"); printf("Numberttweightttparentttlchildttrchildn"); for(i=1;i<=m;i+) printf("%dtt%dtt%dtt%dtt%dn", i,HTi.weight,HTi.parent,HTi.lchild,HTi.rchild); 、哈夫曼树的功能是将每个结点用0
14、和1表示出来,所以将每个结点的哈夫曼编码表示出来也可以确定哈夫曼树的结构。而在Create函数中,同样已经给确定了结点的0值和1值,只需要调用一个字符串函数将每个结点的编码复制到该结点相应的编码值Code中。然后再在主函数中将其打印出来。HCi=(char *)malloc(n-start)*sizeof(char *); /*为第i个字符编码分配空间*/strcpy(HCi,&cdstart); /*从cd复制编码串到HC*/printf("HuffmanCode:n"); printf("NumberttWeightttCoden"); fo
15、r(i=1;i<=n;i+) printf("%dtt%dtt%sn",i,wi,HCi); 五、流程图main函数: Select函数: CreatTree函数: 六、实验结果演示1、当输入的结点个数n2时:2、当输入的结点数n=1时,不存在构建哈夫曼树的问题,输出错误提示:七、在编写程序过程中遇到的困难和解决的方法数据结构上机实验是使我们进一步掌握和深化所学知识的必不可少的内容之一,是后继专业课程的根底,是培养我们综合能力和提高我们科学素养的必不可少的局部,所以我对每次实验都抱以极其认真的态度。在刚开始拿到程序的题目时,不知道从何入手,因为题目表现的比拟抽象,并且
16、自己在写哈夫曼树的过程中都遇到一些困难,所以感觉很难完成。百般无奈之下,回归课件,将哈夫曼树那一节仔细的看了几遍才看懂了编写哈夫曼树的根本思想。程序的重点之一是选择权值最小的两个结点,最开始将问题考虑的太过简单,使用数字排序的冒泡法之类的就能找到最小的两个结点,然后使用完这两个结点后将它们删除掉就可以了。但是在实际操作中,结点的内容是使用数组的形式存储下来的,而数组最麻烦的操作就是在数组中进行插入和删除结点。当时怎么也想不到解决的方法。后来在翻阅C语言的书的时候,看到在判断一个数是否为素数的程序中使用了flag标志,考虑先将所有的结点的flag标志都赋为0,而使用完某个结点后就将它的flag标
17、志改为1,这样就不会出现结点被重复使用的现象了。后来在网上查找类似的程序中发现了一个更好的方法,就是运用结点插入后的本来性质,因为在将结点参加到哈夫曼树中,它一定会有父亲结点,所以先将需要处理的结点的父亲结点全赋予0值,而参加到树中后有了父亲结点,那么父亲结点不再为0,可以通过判断parent=0是否成立来判断结点是否被使用过。这样在很大程度下简化了程序。在构建哈夫曼树的过程中,想到每两个最小权值结点的父亲结点是需要另外存储的,而最开始虽然按照课件上的内容将哈夫曼树的结点数设置成2*n-1个,却不知道如何使用。最初的想法是在选择出两个结点后将它们重新编号,从1开始,然后自然而然它们的父亲结点就
18、为3,依此类推。同样的也是在实际操作中,发现这样做真是自己给自己找麻烦,不仅容易将原来需要处理的结点搞混,重新编号也是一项大工程。后来在同学的帮助下,发现自己思考的太复杂了,可以直接将第一个父亲结点的编号设置为n+1即可,因为只有n个结点需要处理,后面的m-n个结点都是父亲结点。最后一个问题是输出的设置。因为是要构建哈夫曼树,所以理所当然的认为要输出一个树的结构,但是很明显根本不知道要如何实现这一类的操作,所以又一次陷入僵局。在同学的提醒下,改换了思维,只要能够表示出树的结构就可以了,并不一定要将一颗树给画出来。而表现出哈夫曼树的结构可以通过它的编码来显示,也可以通过输出它的父亲结点和孩子结点来表示。好在这两
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 临床基础测试试题及答案
- 船舶消防考试题库及答案
- 教育学概率试题及答案
- 安徽信访考试题及答案
- 广告设计师考点与试题及答案曝光
- 中考试题分式及答案
- 湖州护理考试题及答案
- 2024年广告设计心理与认知试题及答案
- 2024国际设计师设计实践考查试题及答案
- 2024国际商业美术设计师职业发展技能试题及答案
- 农业文化创意产业园项目可行性研究报告
- 2025绿地集团购房合同样本
- GB/T 37507-2025项目、项目群和项目组合管理项目管理指南
- 机器视觉试题答案及解析
- GB 14930.2-2025食品安全国家标准消毒剂
- 攀西地区钒钛磁铁矿铁钛综合回收试验研究
- 电商平台服务协议、交易规则
- 档案数字化存储方式试题及答案
- 《时间的故事》(教学设计)-2024-2025学年人美版(2024)美术一年级下册
- 语文综合实践:走进传统节日探寻文化根脉 课件-【中职专用】高一语文同步课堂(高教版2023基础模块下册)
- 《基于微信小程序的旅游攻略系统设计》10000字
评论
0/150
提交评论