数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx

上传人:b****5 文档编号:8307095 上传时间:2023-01-30 格式:DOCX 页数:21 大小:123.54KB
下载 相关 举报
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx_第1页
第1页 / 共21页
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx_第2页
第2页 / 共21页
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx_第3页
第3页 / 共21页
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx_第4页
第4页 / 共21页
数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx

《数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx(21页珍藏版)》请在冰豆网上搜索。

数据结构课程设计报告十进制二叉树四则运算计算器设计与实现.docx

数据结构课程设计报告十进制二叉树四则运算计算器设计与实现

成绩

中国农业大学

课程设计报告书

(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;i

F.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;i

F.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"

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1