数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx
《数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx(21页珍藏版)》请在冰豆网上搜索。
![数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx](https://file1.bdocx.com/fileroot1/2023-1/30/a55b7502-f8f4-48fb-8854-68ac8e39db51/a55b7502-f8f4-48fb-8854-68ac8e39db511.gif)
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现
成绩
中国农业大学
课程设计报告书
(2010-2011学年夏季学期)
设计题目:
十进制四则运算计算器设计与实现
课程名称:
数据结构
******
班 级:
试验092
学 号:
**********
*******
课程设计报告书格式要求(封皮的背面):
1.课程设计报告书采用统一封面,以左侧为准装订成册。
2.课程设计报告书一律使用标准A4复印纸打印或使用标准A4复印纸手写稿形式上交。
3.课程设计报告书打印的格式要求:
课程设计标题(使用隶书二号字体加黑;一级标题、二级标题分别使用黑体三号、四号字体加黑)
正文(使用宋体小四号,行距20磅)
算法代码及源程序代码(使用TimesNewRoman五号)
十进制四则运算计算器设计与实现
1.问题描述
(1)题目要求:
利用二叉树表示算术表达式的基础上,设计实现一个十进制的四则运算计算器。
(2)基本要求:
由用户输入中缀四则运算表达式,由程序计算所输入四则运算表达式的结果并输出。
(3)测试数据:
12-(-4)*((20+3/5)*8/5)*(-4)#
-(22.7-4208.3)/((2.4+1.6)*12)+4.4-2.9#
10-(-3)*((21+3/5)*8/3)*(-2)#
运行结果:
-515.36
88.7
-335.6
2.需求分析
(1)本程序用于求出用户输入的任意合法四则运算表达式的值。
(2)程序运行后显示提示信息,由用户输入任意四则运算表达式,倘若所输入的表达式不合法程序将报错。
(3)用户输入四则运算表达式完毕,程序将输出运算结果。
(4)测试用的表达式须是由+、-、*、/运算符,括号“(”、“)”与相应的运算数组成。
运算数可以是无符号浮点型或整型,范围在0~65535。
3.概要设计
为了实现上述程序功能,应以字符串表示用户输入的表达式,进而将用户输入的表达式转化为二叉树形式存储供计算的类型。
期间还须用到堆栈数据类型。
(1)二叉树的抽象数据类型定义
ADTBinaryTree{
数据对象:
表达式运算数{num|0表达式运算符{opr|+,-,*,/}
数据关系:
由一个根结点和两棵互不相交的左右子树构成,且树中结点具有层次关系。
根结点必须为运算符,叶子结点必须为运算数。
基本操作:
InitBiTree(&T,&S)
初始条件:
存在一四则运算前缀表达式S。
操作结果:
根据前缀表达式S构造相应的二叉树T。
DestroyBiTree(&T)
初始条件:
二叉树T已经存在。
操作结果:
销毁T。
Value(&T)
初始条件:
二叉树T已经存在。
操作结果:
计算出T所表示的四则运算表达式的值并返回。
}ADTBineryTree
(2)顺序栈的抽象数据类型定义
ADTStack{
数据对象:
具有相同类型及后进先出特性的数据元素集合。
数据关系:
相邻数据元素具有前去和后继关系。
基本操作:
InitStack(&S)
初始条件:
无
操作结果:
构造一个空栈S。
DestroyStack(&S)
初始条件:
栈S已经存在。
操作结果:
销毁S。
StackLength(&S)
初始条件:
栈S已经存在。
操作结果:
返回S中元素个数。
GetTop(S,&e)
初始条件:
栈S已经存在且非空。
操作结果:
用e返回S的栈顶元素。
Push(&S,e)
初始条件:
栈S已经存在。
操作结果:
插入元素e为S的新栈顶元素。
Pop(&S,e)
初始条件:
栈S已经存在且非空。
操作结果:
删除S的栈顶元素,并用e返回其值。
}ADTStack
(3)字符串的抽象数据类型定义
ADTString{
数据对象:
具有字符类型的数据元素集合。
数据关系:
相邻数据元素具有前驱和后继关系。
基本操作:
StrLength(S)
初始条件:
串S已经存在。
操作结果:
返回S的元素个数。
StrNeg(S,F)
初始条件:
串S已经存在且非空。
操作结果:
求S的逆序并将结果保存在串F中。
}ADTString
(4)本程序包含四个模块:
主程序模块;二叉树单元模块(实现二叉树的抽象数据类型,包括结点和指针的定义);顺序栈单元模块(实现顺序栈的抽象数据类型,包含结点和指针的定义);字符串单元模块(实现字符串的抽象数据类型)。
四个模块之间调用关系如下:
4.详细设计
(1)顺序栈类型。
#defineStack_Size100
typedefstruct{
charelem[Stack_Size];
inttop;
}SqStack
基本操作实现的伪代码算法如下:
voidInitStack(SqStack&S){//初始化顺序栈
S.elem=newElemType[Stack_Size];
if(!
S.elem)Error("Overflow!
");
S.top=-1;}
viodPush(SqStack&S,charc){//顺序栈压栈
if(S.top==(Stack_Size-1))Error("StackOverflow!
");
S.elem[++S.top]=c;}
ElemTypePop(SqStack&S){//顺序栈出栈
if(S.top==-1)Error("StackEmpty!
");
returnS.elem[S.top--];}
intStackLength(SqStack&S){//求顺序栈长度
return(S.top+1);}
GetTop(SqStack&S,chare){//取栈顶元素
e=S.elem[top];}
(2)字符串类型
typedefstruct{//动态顺序串
char*ch;
intlength;
}String
基本操作实现的伪代码算法如下:
intStrLength(&S){//求串长
returnS.length;}
voidStrNeg(&S,&F){//求逆序串
if(!
S.length)error(“StringEmpty!
”);
for(i=0;iF.ch[i]=S.ch[length-1-i];}
(3)二叉树类型。
typedefstructTNode{//二叉树结点
uniondata{charoptr;//运算符
intopnd;};//操作数
structTNode*lchild,*rchild
}TNode
typedefTNode*BiTree//二叉树指针
基本操作实现的伪代码算法如下:
intPrecedence(charopr){//判断运算符级别函数;其中*/的级别为2,+-的级别为1;
intlevel;
switch(opr){
case'+':
case'-':
return
(1);break;
case'*':
case'/':
return
(2);break;
case'(':
case')':
case'#':
default:
return(0);break;}
}
boolIsOperator(charopr){//判断输入串中的字符是不是合法操作符
if(op=='+'||op=='-'||op=='*'||op=='/')
returntrue;
else
returnfalse;}
stringConvert(string&Str){//将一个中缀串转换为后缀串,
stringOutput;//输出串
SqStackS;
for(inti=S.length-1;i>=0;i--){//对输入串逆序扫描
if(Str.ch[i]>=48&&Str.ch[i]<=57){
Output.ch[i]=Str.ch[i];//假如是操作数,把它添加到输出串中。
Output.length++;}
if(Str.ch[i]==')')//假如是右括号,将它压栈。
Push(S,Str.ch[i]);
while(IsOperator(s[i])){//如果是运算符
if(top==0||GetTop(S)==')'||Precedence(Str.ch[i])>=Precedence(GetTop(S))){
Push(S,Str.ch[i]);
break;}
else{Pop(S,e);
Output.ch[i]=e;
Output.length++;}}
if(Str.ch[i]=='('){//假如是左括号,栈中运算符逐个出栈并输出,直到遇到右括号。
右括号出栈并丢弃。
while(GetTop(S)!
=')'){
Output.ch[i]=Pop(S);
Output.length++;
}
}
}
while(S.top!
=-1){//假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
Output.ch=Output.ch--;
Output.ch=Pop(S);}
returnoutput;
}
voidCreatBiTree(&T,&S){//由中缀表达式生成表达式二叉树
StringF;
SqStackSq;//用以存放生成的二叉树结点
InitStack(Sq);
F=Convert(S);//求得S的前缀表达式
for(i=F.length-1;i>=0;i--){
If(!
IsOperator(F.ch[i])){
T=newTNode;
T->data=F.ch[i];
T->lchild=NULL;
T->rchild=NULL;
Push(Sq,T)}
else{
T=newTNode;
T->data=F.ch[i];
T->lchild=Pop(Sq);
T->rchild=Pop(Sq);
Push(Sq,T);}
}}
intCalc(inta,charopr,intb){//计算
switch(opr){
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
case'/':
returna/b;
}
}
intValue(TNode*T){
if(T->lchild==NULL&&T->rchild==NULL)
returnT->data;
else
returnCalc(Value(T->lchild),T->data,Value(T->rchild));
};
(4)主函数伪码算法。
voidmain(){
Face();//输出界面及相关信息
do{
cout<<”Pleaseinputanexpression:
”<cin>>Str;
JudgeExp(S);//判断输入的表达式是否合法。
T=CreatBiTree(S);
N=Value(T);
cout<<”Thevalueofthisexpressionis”<cout<<”Todoanothercalculation?
[Y/N]”;
cin>>e;
if(e==’y’)flag=1;
elseflag=0;}while(flag)
}//main
(5)函数调用关系图。
5.调试分析
(1)程序中使用的字符串类型可直接引用C++自带的类型库,没必要自行定义。
(2)算法时间复杂度分析。
对于由表达式字符串生成二叉树的操作,由于是对字符串顺序扫描根据扫描到当前字符的情况决定操作,以n代表输入的表达式字符串长度,则此算法时间复杂度为0(n)。
对于二叉树求值操作,由结点数量决定时间,n为结点个数,则其时间复杂度为O(n)。
(3)算法空间复杂度分析。
构造两个顺序栈各需一个ElemType类型的Stack_Size为100的栈空间,空间复杂度为O
(1)。
各算法中使用的辅助空间均与元素个数无关,是为O
(1)。
6.使用说明
程序运行后用户根据提示输入要计算的四则运算表达式,整型数浮点数均可,注意不要带空格,尽量保证所输入的表达式是合法表达式。
输入完毕后回车键确定,程序输出结果。
7.测试结果
8.附录(带注释的源程序)
//****************************CStack.h******************************//
#include
usingnamespacestd;
#defineStack_Size100
typedefstruct
{//字符类型顺序栈
charelem[Stack_Size];
inttop;
}CStack
voidInitCStack(&S)
{//初始化顺序栈
S.elem=newchar[Stack_Size];
if(!
S.elem)Error("Overflow!
");
S.top=-1;
}
voidPush_C(CStack&S,chare)
{//压栈
if(S.top==(Stack_Size-1))Error("StackOverflow!
");
S.elem[++S.top]=e;
}
charPop_C(CStack&S)
{//出栈
if(S.top==-1)Error("StackEmpty!
");
returnS.elem[top--];
}
charGetTop(&S)
{//取栈顶元素
if(S.top==-1)Error("StackEmpty!
");
returnS.elem[top];
}
intCStackLength(&S)
{//求栈中元素个数
returntop+1;
}
//****************************TStack.h******************************//
#include
#include"Tree.h"
usingnamespacestd;
#defineStack_Size100
typedefstruct
{//二叉树结点类型顺序栈
TNodeelem[Stack_Size];
inttop;
}TStack
voidInitTStack(&S)
{//初始化顺序栈
S.elem=newchar[Stack_Size];
if(!
S.elem)Error("Overflow!
");
S.top=-1;
}
voidPush_T(TStack&S,TNodeT)
{//压栈
if(S.top==(Stack_Size-1))Error("StackOverflow!
");
S.elem[++S.top]=T;
}
TNodePop_T(TStack&S)
{//出栈
if(S.top==-1)Error("StackEmpty!
");
returnS.elem[top--];
}
//****************************String.h******************************//
#include
usingnamespacestd;
typedefstruct//动态顺序串
{
char*ch;
intlen;
}String
SrtingStrNeg(&Str)//求逆序串
{
StringF;
for(i=0;iF.ch[i]=Str.ch[Str.len-1-i];
returnF
}
intStrLen(&Str)//求串长
{
inti;
for(i=0;Str.ch[i]!
='\0';)i++;
returni;
}
//****************************Tree.h******************************//
#include
#include"String.h"
#include"CStack.h"
#include"TStack.h"
usingnamespacestd;
typedefstruct
{//二叉树结点
uniondata
{//数据域
charopr;//运算符
intopn;//运算数
}
structTNode*lchid,*rchild;//指针域
}TNode
typedefTNode*BiTree;//二叉树头结点
intPrecedence(charopr)
{//判断运算符级别函数;其中*/的级别为2,+-的级别为1;
switch(opr)
{
case'+':
case'-':
return1;break;
case'*':
case'/':
return2;break;
case'(':
case')':
case'#':
default:
return0;break;
}
}
boolIsOperator(charopr)
{//判断输入串中的字符是不是合法操作符
if(op=='+'||op=='-'||op=='*'||op=='/')
returntrue;
else
returnfalse;
}
StringConvert(String&Str)//将一个中缀串转换为后缀串
{
inti;
StringOutput;//输出串
Output.len=0;
CStackS;
InitCStack(S);
Str.len=StrLen(Str);//求的输入的串长
for(i=Str.len-1;i>=0;i--)//对输入串逆序扫描
{
if(Str.ch[i]>=48&&Str.ch[i]<=57)//假如是操作数,把它添加到输出串中。
{
Output.ch[Str.len-1-i]=Str.ch[i];
Output.len++;
}
if(Str.ch[i]==')')//假如是右括号,将它压栈。
Push_C(S,Str.ch[i]);
while(IsOperator(Str.ch[i]))//如果是运算符
{
if(S.top==0||GetTop(S)==')'||Precedence(Str.ch[i])>=Precedence(GetTop(S)))
{
Push_C(S,Str.ch[i]);
break;
}
else
{
Output.ch[Str.len-1-i]=Pop_C(S);
Output.len++;
}
}
if(Str.ch[i]=='(')//假如是左括号,栈中运算符逐个出栈并输出
{//直到遇到右括号。
右括号出栈并丢弃。
while(GetTop(S)!
=')')
{
Output.ch[Str.len-1-i]=Pop_C(S);
Output.len++;
}
}
}
while(S.top!
=-1)//假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
{
Output.ch[++Output.len-1]=Pop_C(S);
}
returnStrNeg(Output);//输出Output的逆序即为所求前缀表达式
}
voidCreatBiTree(&T,&Str)//由中缀表达式生成表达式二叉树
{
StringF;
TStackS;//用以存放生成的二叉树结点
InitTStack(S);
F=Convert(Str);//求得S的前缀表达式
for(i=F.len-1;i>=0;i--)
{
if(!
IsOperator(F.ch[i]))
{
T=newTNode;
T->data=F.ch[i];
T->lchild=NULL;
T->rchild=NULL;
Push_T(S,T)
}
else
{
T=newTNode;
T->data=F.ch[i];
T->lchild=Pop_T(S);
T->rchild=Pop_T(S);
Push_T(S,T);
}
}
}
intCalc(inta,charopr,intb)//计算
{
switch(opr)
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
case'/':
returna/b;
}
}
intValue(TNode*T)//求表达式二叉树的值
{
if(T->lchild==NULL&&T->rchild==NULL)
returnT->data;
else
returnCalc(Value(T->lchild),T->data,Value(T->rchild));
}
//****************************JudgeExp.h******************************//
#include
#include"String.h"
#include"Tree.h"