数据结构课程实习报告Word文件下载.docx
《数据结构课程实习报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《数据结构课程实习报告Word文件下载.docx(44页珍藏版)》请在冰豆网上搜索。
4.程序及算法分析
在main函数开头输入运算阶乘的数据number,然后从2开始做乘法运算,如果超过10就向前进位,如果没有前节点就insert,如果有就加在前节点的data域上面,如果加了之后有大于10,就循环前面的步骤,然后将链表的数值一个个给数组,倒过来输出就是结果了。
链表的insert是往前面插,所以输出的时候有点麻烦,所以我引进了一个中间的数组来帮助输出,要是做的链表是向后插的话就比较好输出,这是值得改进的。
还有就是在main里写代码不是太好,所以吧那部分放到一个函数里就比较简洁了。
体会是想清楚了控制判断,把程序写出来还是比较容易的。
需要花时间、
5.附录
【代码】
#include"
stdafx.h"
iostream.h"
template<
classT>
classChain;
classChainNode
{//将chain声明为chainnode的友元以
//使其访问chainnode的私有变量
friendChain<
T>
;
public:
Tdata;
ChainNode<
*link;
classChain
{
Chain(){first=0;
}
~Chain();
Chain<
&
Delete(intk,T&
x);
Insert(intk,constT&
*first;
Chain<
:
~Chain()
ChainNode<
*next;
while(first)
{
next=first->
link;
deletefirst;
first=next;
}
Chain<
Delete(intk,T&
x)
{//delete的实现
*p=first;
if(k==1)
first=first->
else
*q=first;
for(intindex=1;
index<
k-1&
q;
index++)
{
q=q->
}
p=q->
q->
link=p->
x=p->
data;
deletep;
return*this;
Insert(intk,constT&
{//insert的实现
if(k<
0)
{cout<
<
"
outofbound!
endl;
*p=first;
for(intindex=1;
k&
p;
p=p->
if(k>
0&
!
p)
*y=newChainNode<
y->
data=x;
if(k)
y->
p->
link=y;
link=first;
first=y;
intmain(intargc,char*argv[])
{//i为临时变量total是表示和的大小
//rest是看进位的数值大小
inti=0,count=2,number,total,rest=0,j=0;
intNO[100];
//在最后要倒置是用到的临时数组
cout<
EnteraNumber:
cin>
>
number;
int>
chain;
chain.Insert(0,1);
*currentfirst=chain.first;
//保存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
data=total;
currentfirst=currentfirst->
currentfirst=chain.first;
rest=0;
//清零,不然下次加的时候受上次运算的影响
total=0;
currentfirst=chain.first;
for(i=0;
i<
=j;
i++)
NO[i]=currentfirst->
//currentfirst只有有限个,不一定有100个!
currentfirst=currentfirst->
//输出
cout<
NO[j-i];
return0;
【输出】
实习题二
对一个合法的中缀表达式求值
假设表达式只包含+,-,*,/四个双目运算符,并且运算符本身不具有二义性。
1.正确的解释表达式;
2.符合四则运算法则;
3.输出后计算结果;
为每一个运算符设定一个优先级,然后根据输入的中序表达式将其变成后序表达式,在根据后序表达式求得表达式的值。
抽象数据类型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中,当然,在用这个函数的时候是要在函数体外声明这样一个参数的。
然后从左到右依次扫描表达式的个单词,如果是操作数,存入栈中,如果是运算符,就提取前面的两个操作数(从栈中弹出两个数)进行运算,中间结果同样存入栈中作为下一个运算的操作数。
如此反复直到表达式处理完毕。
计算器做起来比较复杂,我做了将近两个星期才做好。
主要是calculate函数和postpix函数。
在ppt上面的基础上想好思路倒是不难,但是实现起来总会不如意,这时候调试的功能就来了,也是在这一次我真正开始调试,因为每次总要先看看栈顶的东西是什么。
所以根据调试来发现错误是解决这一个题目的关键,我认为。
在发现了栈顶的错误跟if判断的局限性之后才好改动compare函数和level函数。
所以最终这题是调试出来的。
使用的时候输入要求的算式的中缀表达式,然后就按回车键,屏幕上就可以输出计算得到的后缀表达式和计算的结果。
虽然在大多数情况下可以正常输出,但是,总有一些时候他得不到正确的结果。
就是表明这个程序并不是稳定的。
有出错的可能,像这样的不完整的程序是比较危险的。
但由于时间和精力有限。
我到现在只能调试到这个地步。
在此基础上仍有很大的提升空间。
开始的时候我是想用MFC做的。
但是太麻烦加上时间也不够。
就只能退而求其次。
如果有时间我回继续做的。
intlevel(chara)
{//level函数,返回某个操作符的优先级
intlevelresult=-2;
switch(a)
case'
+'
levelresult=0;
break;
-'
*'
levelresult=1;
/'
('
levelresult=2;
)'
levelresult=-1;
#'
default:
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;
)
return0;
}
compareerror!
//在比较中出现的错误
return-1;
//错误的比较
voidpostfix(charstr[],charstrResult[])
{//变后缀表达式的函数
//返回strresult
Stake<
char>
stake;
stake.Add('
);
chartemp;
boolseprate=false;
inti=0;
for(;
str[i]!
=0;
{
if(str[i]>
0'
str[i]<
'
9'
strResult[index]=str[i];
index++;
if(str[i+1]>
str[i+1]<
{
seprate=false;
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);
if(stake.Top()=='
while(!
stake.IsEmpty()&
stake.Top()!
chartemp;
if(stake.Top()=='
//得到结果数组
strResult[index]=stake.Top();
//删除top
stake.Delete(temp);
index++;
voidcalculate(charstrResult[],double&
result)
{//计算函数
//从结果数组求得最后的结果
double>
numberstake;
doubletempa,tempb,tempc,waste;
char*temp;
temp=newchar[];
index;
intj=0;
if(strResult[i]>
strResult[i]<
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.Add(tempa+tempb);
elseif(strResult[i]=='
{//如果是+就把栈顶两个数的余压入栈中
numberstake.Add(tempb-tempa);
{//如果是*就把栈顶两个数的积压入栈中
numberstake.Add(tempa*tempb);
{//如果是/就把栈顶两个数的商压入栈中
numberstake.Add(tempa/tempb);
//numberstake的栈顶就是结果
result=numberstake.Top();
char*str,*strResult;
str=newchar[];
strResult=newchar[];
str;
postfix(str,strResult);
strResult[i];
doubleresult;
calculate(strResult,result);
result<
实习题三
以二叉链表作为二叉树的存储结构建立二叉树,并对其进行操作,基本功能要求:
(1)建立一棵二叉树;
(2)对该二叉树进行前序、中序、后序、层序遍历;
(3)统计该二叉树叶子结点的个数。
(4)求二叉树的深度。
(5)用非递归方法实现二叉树的中序遍历。
从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序)、统计叶节点个数、求二叉树的深度并用非递归方法实现二叉树的中序遍历和层序遍历,将结果打印输出,。
建立BinaryTree类,并且在类中声明数据成员和函数成员,其中数据成员包括树的根节点,函数成员包括前序遍历,中序遍历和后续遍历,层序遍历。
共有函数包括得到叶子节点函数和判等函数和改变叶子函数。
实现对二叉树的操作。
抽象数据类型BinaryTree{
实例
根节点
Creat():
创建一个空的二叉树;
如果二叉树为空,返回true,否则返回false;
Root(x):
取x为根节点,如果操作失败,返回false否则返回true;
Creat:
创建树;
PreOrder:
前序遍历;
InOrder:
中序遍历;
PostOrder:
后续遍历;
LevelOrder:
层序遍