数据结构课程实习报告.docx
- 文档编号:3869026
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:44
- 大小:158.49KB
数据结构课程实习报告.docx
《数据结构课程实习报告.docx》由会员分享,可在线阅读,更多相关《数据结构课程实习报告.docx(44页珍藏版)》请在冰豆网上搜索。
数据结构课程实习报告
数据结构实习报告
课程名称:
指导老师:
学生姓名:
班级:
学号:
实习题一
1.需求规格说明
【问题描述】
大数运算——计算n的阶乘(n大于等于20)
【基本要求】
数据的表示和存储:
累积运算的中间结果和最终的计算结果的数据类型要求是整型,试设计合适的存储结构,要求每个元素或结点最多存储数据的3位数值。
数据的操作及其实现:
基于设计的存储结构实现乘法操作,要求从键盘上输入n值;在屏幕上显示最终计算结果。
2.总体分析与设计
【设计思想】
因为大数的阶乘算出来的数值比较大,位数远远超过一个int或double行的位数,为了精确性的考虑,阶乘后的结果要用一种存储结构来存储并且累加和处理。
所以要设计一个这样的数据结构实现对数据的存储,例如让每个存储单元只存储一部分的数值,在也运算的时候采用算数运算的进位方法来运算。
【设计表示】
抽象数据类型Chain{
实例
链表头指针
操作
Chain():
将链表头指针赋值为零;
Delete(k,x):
删除第k个元素并且把它存在x中;
Insert(k,x):
把x存到第k个节点;
};
定义一个ChainNode模板类来表示链表类的成员变量,其主要包含两个数据域,data和link,data表示节点的数值域,link表示链接域。
然后在定义一个Chain类模板来表示要存储数据的数据类型包含first头指针和insert还有delete函数,insert用来添加节点,delete用来删除节点,first永远指向链表的头指针,以保存这个链表的完整性。
在主函数中加一些代码来实现大数的阶乘过程中链表的操作,在进位时,如果没有高位,就insert一个节点并且将进位的数据插到生成的节点当中,当向高位进位的时候,如果有高位就将仅为的数值和原高位相加,判断是否需要在进位,循环上述判断。
3.编码
开始做的时候每一个节点中的数值运算不太好处理,毕竟不是int,乘法的时候进位的判断和加法,循环等十分复杂,判断语句很难实现好。
解决方法就是调试了一个星期,把每个判断与循环做好注释,在跟踪的时候看哪个判断出了问题,在注意解决,这题还比较简单,所以比较好调。
4.程序及算法分析
在main函数开头输入运算阶乘的数据number,然后从2开始做乘法运算,如果超过10就向前进位,如果没有前节点就insert,如果有就加在前节点的data域上面,如果加了之后有大于10,就循环前面的步骤,然后将链表的数值一个个给数组,倒过来输出就是结果了。
链表的insert是往前面插,所以输出的时候有点麻烦,所以我引进了一个中间的数组来帮助输出,要是做的链表是向后插的话就比较好输出,这是值得改进的。
还有就是在main里写代码不是太好,所以吧那部分放到一个函数里就比较简洁了。
体会是想清楚了控制判断,把程序写出来还是比较容易的。
需要花时间、
5.附录
【代码】
#include"stdafx.h"
#include"iostream.h"
template
classChain;
template
classChainNode
{//将chain声明为chainnode的友元以
//使其访问chainnode的私有变量
friendChain
public:
Tdata;
ChainNode
};
template
classChain
{
public:
Chain(){first=0;}
~Chain();
Chain
Chain
ChainNode
};
template
Chain
:
~Chain()
{
ChainNode
while(first)
{
next=first->link;
deletefirst;
first=next;
}
}
template
Chain
:
Delete(intk,T&x)
{//delete的实现
ChainNode
if(k==1)
{
first=first->link;
}
else
{
ChainNode
for(intindex=1;index { q=q->link; } p=q->link; q->link=p->link; } x=p->data; deletep; return*this; } template Chain : Insert(intk,constT&x) {//insert的实现 if(k<0) {cout<<"outofbound! "< ChainNode for(intindex=1;index { p=p->link; } if(k>0&&! p) {cout<<"outofbound! "< ChainNode y->data=x; if(k) { y->link=p->link; p->link=y; } else { y->link=first; first=y; } return*this; } intmain(intargc,char*argv[]) {//i为临时变量total是表示和的大小 //rest是看进位的数值大小 inti=0,count=2,number,total,rest=0,j=0; intNO[100];//在最后要倒置是用到的临时数组 cout<<"EnteraNumber: "< cin>>number; Chain chain.Insert(0,1); ChainNode //保存chain的first以免破坏chain for(count=2;count<=number;count++) { while(currentfirst) { total=(currentfirst->data)*count+rest; //total是当前节点的值大小从小到大乘 //直到乘到输入数据number rest=0; if(total>9) {//如果大于十取余 currentfirst->data=total%10; rest=total/10;//rest表示取余后的大小 if(! (currentfirst->link)) {//如果没有上一节点,insert j++; i++; chain.Insert(i,0); } } else {//total小于10 currentfirst->data=total; } currentfirst=currentfirst->link; } currentfirst=chain.first; rest=0;//清零,不然下次加的时候受上次运算的影响 total=0; } currentfirst=chain.first; for(i=0;i<=j;i++) { NO[i]=currentfirst->data;//currentfirst只有有限个,不一定有100个! currentfirst=currentfirst->link; } //输出 for(i=0;i<=j;i++) { cout< } cout< return0; } 【输出】 实习题二 1.需求规格说明 【问题描述】 对一个合法的中缀表达式求值 假设表达式只包含+,-,*,/四个双目运算符,并且运算符本身不具有二义性。 【基本要求】 1.正确的解释表达式; 2.符合四则运算法则; 3.输出后计算结果; 2.总体分析与设计 【设计思想】 为每一个运算符设定一个优先级,然后根据输入的中序表达式将其变成后序表达式,在根据后序表达式求得表达式的值。 【设计表示】 抽象数据类型Stake{ 实例 元素线性表,栈回底,栈顶 操作 IsEmpty(): 如果栈为空,返回true,否则回false IsFull(): 如果栈满,返回true,否则返回false Top(): 返回栈顶指针; Add(x): 向栈中加元素x; Delete(x): 删除栈顶元素存在x中; } 顶点i的入度 先写级函数,这里写的是level函数,传入的是操然后返回其优先级,左括号‘(’的优先级最大。 设置为2,右括号‘)’和‘#’的优先级最小,设置为-1.在就是加法还有减法的优先级相同为0乘法和除法的优先级比加减法大为1.这是所有比较的依据,最基本的寒素,然后是比较函数,在入栈和出栈过程中频繁调用,其传入的是两个运算符(char型),然后调用level函数,判断其返回值的大小,如果前一个的优先级大就返回1,否则返回0,如果相等也返回0,但是如果传入的值有‘(’或‘)’,则再加特殊判断。 然后是后续表达式函数,这里是postpix函数。 将用户输入的字符型数组传入,然后将后续表达式的数组传出。 中间根据栈的一系列特性和运算符优先级关系进行出栈和入栈操作,最后保存在结果数组中。 最后一步就是将后续表达式传入计算函数这里是calculate函数,将后续表达式也通过运算和栈操作实现计算值的功能。 在详细设计表示主要讲calculate函数和postpix函数,postpix函数有两个传入参数,charstr[]和charstrResult[],其中前者是用户输入的数组,后者是需要得到的结果后缀表达式数组。 首先在自定义的栈中压入‘#’,因为开始的时候栈中是没有符号的,也就没有优先级的分别,这里把‘#’压倒里面去就是为了后面可以比较符号优先级。 然后优先级高的压栈,优先级低的直接放到结果数组中,如果是数字也是直接放到结果数组中。 如果有括号,出栈或者入栈但是不放到结果数组中,因为他们不需要操作。 这样就得到了后缀表达式。 Calculata则是一个根据得到的后缀表达式求值的函数,其函数参数是后缀表达式和一个浮点数的变量的引用。 在strResult传入函数中去之后将结果保存在result中,当然,在用这个函数的时候是要在函数体外声明这样一个参数的。 然后从左到右依次扫描表达式的个单词,如果是操作数,存入栈中,如果是运算符,就提取前面的两个操作数(从栈中弹出两个数)进行运算,中间结果同样存入栈中作为下一个运算的操作数。 如此反复直到表达式处理完毕。 3.编码 计算器做起来比较复杂,我做了将近两个星期才做好。 主要是calculate函数和postpix函数。 在ppt上面的基础上想好思路倒是不难,但是实现起来总会不如意,这时候调试的功能就来了,也是在这一次我真正开始调试,因为每次总要先看看栈顶的东西是什么。 所以根据调试来发现错误是解决这一个题目的关键,我认为。 在发现了栈顶的错误跟if判断的局限性之后才好改动compare函数和level函数。 所以最终这题是调试出来的。 4.程序及算法分析 使用的时候输入要求的算式的中缀表达式,然后就按回车键,屏幕上就可以输出计算得到的后缀表达式和计算的结果。 虽然在大多数情况下可以正常输出,但是,总有一些时候他得不到正确的结果。 就是表明这个程序并不是稳定的。 有出错的可能,像这样的不完整的程序是比较危险的。 但由于时间和精力有限。 我到现在只能调试到这个地步。 在此基础上仍有很大的提升空间。 开始的时候我是想用MFC做的。 但是太麻烦加上时间也不够。 就只能退而求其次。 如果有时间我回继续做的。 【代码】 intlevel(chara) {//level函数,返回某个操作符的优先级 intlevelresult=-2; switch(a) { case'+': levelresult=0; break; case'-': levelresult=0; break; case'*': levelresult=1; break; case'/': levelresult=1; break; case'(': levelresult=2; break; case')': levelresult=-1; break; case'#': levelresult=-1; break; default: cout<<"levelerror! "< } returnlevelresult;//返回优先级 } intcompare(chara,charb) {//比较两个操作符的优先级大小 //如果操作符a>b,返回1。 否则返回0 intlevel1=0; intlevel2=0; level1=level(a); level2=level(b); if(level1>level2) { return1; } elseif(level1<=level2) { if(b==')'&&a! ='(') { return1; } if(b=='(') { return1; } return0; } cout<<"compareerror! "< return-1;//错误的比较 } voidpostfix(charstr[],charstrResult[]) {//变后缀表达式的函数 //返回strresult Stake stake.Add('#'); chartemp; boolseprate=false; inti=0; for(;str[i]! =0;i++) { if(str[i]>='0'&&str[i]<'9') { strResult[index]=str[i]; index++; if(str[i+1]>='0'&&str[i+1]<'9') { seprate=false; } else { strResult[index]=''; index++; } } //优先级大的压栈 elseif(compare(str[i],stake.Top())==1) { stake.Add(str[i]); } //优先级小的出栈 elseif(compare(str[i],stake.Top())==0) { if(stake.Top()=='(') { stake.Delete(temp); } //stake.Delete(temp);//havestored')'! strResult[index]=stake.Top(); stake.Delete(temp); index++; if(stake.Top()=='(') { stake.Delete(temp); } stake.Add(str[i]); if(stake.Top()==')') { stake.Delete(temp); } } } while(! stake.IsEmpty()&&stake.Top()! ='#') { chartemp; if(stake.Top()=='(') { stake.Delete(temp); } if(stake.Top()==')') { stake.Delete(temp); } //得到结果数组 strResult[index]=stake.Top(); //删除top stake.Delete(temp); index++; } } voidcalculate(charstrResult[],double&result) {//计算函数 //从结果数组求得最后的结果 Stake inti=0; doubletempa,tempb,tempc,waste;; char*temp; temp=newchar[]; for(;i { intj=0; if(strResult[i]>='0'&&strResult[i]<='9') { while(j>=0) { temp[j]=strResult[i]; j++; if(strResult[i+1]=='') { j=-1; } if(strResult[i+1]! ='') { i++; } } //atof的参数是char型数组不是char型数组数据 tempc=atof(temp); numberstake.Add(tempc); } if(strResult[i]=='+') {//如果是+就把栈顶两个数的和压入栈中 tempa=numberstake.Top(); numberstake.Delete(waste); tempb=numberstake.Top(); numberstake.Delete(waste); numberstake.Add(tempa+tempb); } elseif(strResult[i]=='-') {//如果是+就把栈顶两个数的余压入栈中 tempa=numberstake.Top(); numberstake.Delete(waste); tempb=numberstake.Top(); numberstake.Delete(waste); numberstake.Add(tempb-tempa); } elseif(strResult[i]=='*') {//如果是*就把栈顶两个数的积压入栈中 tempa=numberstake.Top(); numberstake.Delete(waste); tempb=numberstake.Top(); numberstake.Delete(waste); numberstake.Add(tempa*tempb); } elseif(strResult[i]=='/') {//如果是/就把栈顶两个数的商压入栈中 tempa=numberstake.Top(); numberstake.Delete(waste); tempb=numberstake.Top(); numberstake.Delete(waste); numberstake.Add(tempa/tempb); } elseif(strResult[i]=='') { } } //numberstake的栈顶就是结果 result=numberstake.Top(); } intmain(intargc,char*argv[]) { inti=0; char*str,*strResult; str=newchar[]; strResult=newchar[]; cin>>str; postfix(str,strResult); for(;i { cout< } cout< doubleresult; calculate(strResult,result); cout< return0; } 【输出】 实习题三 1.需求规格说明 【问题描述】 以二叉链表作为二叉树的存储结构建立二叉树,并对其进行操作,基本功能要求: (1)建立一棵二叉树; (2)对该二叉树进行前序、中序、后序、层序遍历; (3)统计该二叉树叶子结点的个数。 (4)求二叉树的深度。 (5)用非递归方法实现二叉树的中序遍历。 【基本要求】 从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序)、统计叶节点个数、求二叉树的深度并用非递归方法实现二叉树的中序遍历和层序遍历,将结果打印输出,。 2.总体分析与设计 【设计思想】 建立BinaryTree类,并且在类中声明数据成员和函数成员,其中数据成员包括树的根节点,函数成员包括前序遍历,中序遍历和后续遍历,层序遍历。 共有函数包括得到叶子节点函数和判等函数和改变叶子函数。 实现对二叉树的操作。 【设计表示】 抽象数据类型BinaryTree{ 实例 根节点 操作 Creat(): 创建一个空的二叉树; IsEmpty(): 如果二叉树为空,返回true,否则返回false; Root(x): 取x为根节点,如果操作失败,返回false否则返回true; Creat: 创建树; PreOrder: 前序遍历; InOrder: 中序遍历; PostOrder: 后续遍历; LevelOrder: 层序遍
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程 实习 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)