c++数据结构实验哈夫曼树.docx_第1页
c++数据结构实验哈夫曼树.docx_第2页
c++数据结构实验哈夫曼树.docx_第3页
c++数据结构实验哈夫曼树.docx_第4页
c++数据结构实验哈夫曼树.docx_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

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

文档简介

北京邮电大学信息与通信工程学院数据结构实验报告1实验要求i. 实验目的:(1) 掌握二叉树基本操作的实现方法(2) 掌握二叉树基本操作的实现方法(3) 了解哈夫曼树的思想和相关概念(4) 学习使用二叉树解决实际问题的能力(5) 熟悉C+语言的基本编程方法,掌握集成编译环境的调试方法,熟练改错方 法。(6) 熟悉设计算法的过程(7) 进一步掌握指针、异常处理的使用ii. 实验内容:利用二叉树结构实现赫夫曼编/解码器。基本要求:1、 初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、 建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。3、 编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。4、 译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。5、 打印(Print):以直观的方式打印赫夫曼树(选作)6、 计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。测试数据: I love data Structure, I love Computer.I will try my best to study data structure. 提示: 1、用户界面可以设计为“菜单”方式:能够进行交互。 2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。iii. 代码要求:1、必须要有异常处理,比如删除空链表时需要抛出异常;2、保持良好的编程的风格:代码段与段之间要有空行和缩近标识符名称应该与其代表的意义一致函数名之前应该添加注释说明该函数的功能关键代码应说明其功能 3、递归程序注意调用的过程,防止栈溢出2. 程序分析树形结构是一种非线性结构可以用结点之间的分支来表示层次关系,二叉树是每个结点最多两个子树的有序树,十分适合计算机处理问题,而哈夫曼树是一种特殊的二叉树,它将权值大的数据放在了离根较近的结点处,这样使得带权路径长度最短,是非常好的存储方式。2.1 存储结构1.结点结构的存储方式:根(下面结点的父结点)结点:左孩子右孩子 struct hnode /哈夫曼树结点的结构体int weight;int parent;int lchild;int rchild;char data;结点存储示意图:int weightint parentint lchildint rchildchar data2.编码表的实现中使用了以下结构体:Struct hcode /编码表结构体char data; /字符char code100; /编码内容;示意图为:char datachar code1003.在select函数中使用的结构体:struct nodeint num;char data;int numchar data2.2 关键算法分析:A)Init初始化:统计需要编码的字符串中每个字符的频度并建立哈夫曼树实现:在函数中设置了一个数组type用来统计字符串中字符的类型,no数组则用于统计每种字符串的个数,count用于存储每类字符的相应的个数。void Huffman:Init() /将输入的数据保存至类中cout 请输入需要编译压缩的内容 endl;cin.getline(in, 500, n);n = 0;no = 0;count = new node127; /typefor (int j = 0; j 127; j+) /对每一种字符的个数进行初始化 countj.num = 0;while (inno != 0) /结束之前,每输入一个字符,则对应的数目增1+countinno.num;countinno.data = inno;+no;for (int k = 0; k0)n+;cout countk.data countk.num endl;将初始化的数据用于建立哈夫曼树:void Huffman:createht()no = 0;htree = new hnode2 * n - 1;/含有n种字符的哈夫曼树需要2*n-1个结点for (int i = 0; in; i+)while (countno.num = 0) /该字符没有出现,跳过,继续找出现过的字符no+;htreei.weight = countno.num; /将count里统计的次数传入哈夫曼树的节点中,作为字符权重htreei.lchild = -1;htreei.rchild = -1;htreei.parent = -1; /将左右孩子结点和父节点都置空htreei.data = countno.data; /将字符传入哈夫曼树的结点no+;int x = -1, y = -1;for (int i = n; i 2 * n - 1; i+)SelectMin(x, y, i); /挑选三者中的权重较小的两个htreex.parent = htreey.parent = i; /令较小的x、y为孩子节点,该两个结点的父节点是ihtreei.weight = htreex.weight + htreey.weight;/i结点字符的权重赋为是左右孩子字符权重之和htreei.lchild = x; /左孩子为xhtreei.rchild = y; /右孩子为yhtreei.parent = -1; /父节点置空x = -1;y = -1;注意select函数的编写十分重要,必须成功选出每次权值最小的两个数据才能正确的建立哈夫曼树void Huffman:SelectMin(int &x, int &y, int k) /选出权值较小的两个字符结点int i = 0;while (i k)while (i k&htreei.parent = -1) /当前结点不具有父结点且满足ik则进行循环if (x = -1) /左孩子x = i;else if (y = -1)y = i;elseif (htreex.weight = htreey.weight)if (htreey.weight htreey.weight)if (htreei.weight = htreex.weight)x = x; y = y;elsex = i;i+;i+;B)create table建立编码表:利用初始化得到的结果将哈夫曼树进行编码并输出每个字符的编码。1.在程序中设置了一个数组save来存储每个字符的编码。void Huffman:createhc() /建立哈夫曼编码表hcodetable = new hcoden; /生成编码表for (int i = 0; in; i+)hcodetablei.data = htreei.data;int child = i;int parent = htreei.parent;int k = 0;while (parent != -1)if (child = htreeparent.lchild) /该节点是父节点的左孩子则编码为0,右孩子则编码为1hcodetablei.codek = 0;elsehcodetablei.codek = 1;k+;child = parent; /将该节点的父节点进行编码输出parent = htreechild.parent;hcodetablei.codek = 0; /code数组以0结尾Reverse(hcodetablei.code); /逆置输出字符的编码值cout 每个字符的编码为: endl;for (int i = 0; in; i+)cout hcodetablei.data : hcodetablei.code = 0) /通过t数组将use数组内的数据逆序排序usej = ti;i-;j+;usej = 0;C).Encoding根据编码表对输入的字符串进行编码,并将编码后的字符串进行输出。 void Huffman:Encoding() /编译输入内容为代码内容用0和1表示cout 编码结果为:;int k = 0;for (int i = 0; ini != 0; i+)int j = 0;while (hcodetablej.data != ini) /编码表的字符等于输入内容的字符时进行下一个while循环j+;int m = 0;while (hcodetablej.codem != 0)/输出该字符的编码savek = hcodetablej.codem;/save数组记录编码数据cout savek endl;k+;m+;savek = 0;cout endl;D).Decoding译码:利用建好的哈夫曼树对编码后的字符串进行译码,并输出译码的结果。void Huffman:Decoding()cout 解码结果为:;int i = 0, j = 0;while (savei != 0)int child = 2 * n - 1 - 1;/找到保存根节点的数组数 while (htreechild.lchild != -1)/若是这个节点父节点的孩子存在则继续向下寻找if (savei = 0)child = htreechild.lchild; /是0则找左孩子elsechild = htreechild.rchild; /是1则找右孩子i+;cj = hcodetablechild.data; /若不存在孩子节点,则令数组的元素为该节点的字符变量cout cj;j+; /逐个输出字符内容E).print打印:以直观的方式打印哈夫曼树通过递归调用从根结点开始以中序遍历的方式打印出树void Huffman:printtree(int qi, int f)if (htreeqi.lchild != -1)printtree(htreeqi.lchild, f + 4);cout setw(f);if (qi n)cout hcodetableqi.data endl;elsecout htreeqi.weight endl;if (htreeqi.rchild != -1)printtree(htreeqi.rchild, f + 4);F).计算输入输出前后编码长度并进行分析讨论压缩效果int Huffman:getsizea()return strlen(in);int Huffman:getsizeb()return strlen(save);(b - a)即为所求。2.3 其他1.哈夫曼树的类:class Huffmanprivate:hnode*htree; /哈夫曼树hcode*hcodetable; /哈夫曼编码表char c127; /字符类型node*count; /记录各个字符及其出现次数int n; /输入字符的种类的个数int no; /输入字符的个数char in500; /保存输入的字符串char save500; /记录所有输入内容被编码后的结果public:void createht(); /创建哈夫曼树void createhc(); /创建编码表void Init(); /初始化void Encoding(); /编码void Decoding(); /解码void SelectMin(int &x, int &y, int k);/求最小权重的字符int getsizea();int getsizeb();void printtree(int qi, int f); /打印哈夫曼树;int getn();Huffman();2.switch语句:switch (choice)case 1:ht.Init();break;case 2:ht.Encoding();break;case 3:ht.Decoding();break;case 4: ht.printtree(2*qi-1-1,f);break;case 5:cout 压缩前 b bit 压缩后 a bit endl;cout 压缩了 (b - a) 个bit endl;break;default:break;3.计算时间复杂度:A) o(n);B)o(n);C) o(n);D)o(n);E) o(n);F)o(1);3. 程序运行结果1.程序流程图:开始输入所需编码的字符串 否n是否小于500? 是init初始化哈夫曼树Switch语句。选择所需调用的函数 调用所需调用的函数,显示相应的数据 否Switch语句是否调用完毕是结束2.测试条件:输入字符串的长度小于500;3.测试结论:4. 总结在这次实验中我通过不断的调试,理解了树的结构与哈夫曼树编解码的代码,并且回忆了上学期c+中学习到的知识,编写了select和reverse函数,在编程过程中出了许多错误:1. 是在switch语句中赋值,经过程序提示改为了在主函数中赋值void main()Huffman ht;ht.Init();ht.createht();ht.createhc();ht.Encoding();ht.Decoding();int f = 0;int qi = ht.getn();int a = ht.getsizea();int b = ht.getsizeb();menu();int choice = 1;for (int p = 0; p choice;switch (choice)case 1:ht.Init();break;case 2:ht.Encoding();break

温馨提示

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

最新文档

评论

0/150

提交评论