湖南大学数据结构四则运算表达式报告.docx

上传人:b****6 文档编号:6170179 上传时间:2023-01-04 格式:DOCX 页数:13 大小:151.92KB
下载 相关 举报
湖南大学数据结构四则运算表达式报告.docx_第1页
第1页 / 共13页
湖南大学数据结构四则运算表达式报告.docx_第2页
第2页 / 共13页
湖南大学数据结构四则运算表达式报告.docx_第3页
第3页 / 共13页
湖南大学数据结构四则运算表达式报告.docx_第4页
第4页 / 共13页
湖南大学数据结构四则运算表达式报告.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

湖南大学数据结构四则运算表达式报告.docx

《湖南大学数据结构四则运算表达式报告.docx》由会员分享,可在线阅读,更多相关《湖南大学数据结构四则运算表达式报告.docx(13页珍藏版)》请在冰豆网上搜索。

湖南大学数据结构四则运算表达式报告.docx

湖南大学数据结构四则运算表达式报告

实验4四则运算表达式求值

背景

在工资管理软件中,不可避免的要用到公式的定义及求值等问题。

对于数学表达式的计算,虽然可以直接对表达式进行扫描并按照优先级逐步计算,但也可以将中缀表达式转换为逆波兰表达式,这样更容易处理。

问题描述

四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。

基本要求

(1)使用二叉树来实现。

实现提示

利用二叉树后序遍历来实现表达式的转换,同时可以使用栈来求解后缀表达式的值。

输入输出格式:

输入:

在字符界面上输入一个中缀表达式,回车表示结束。

输出:

如果该中缀表达式正确,那么在字符界面上输出其后缀表达式和计算结果,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

选作内容

(1)在输入输出方式上要求使用:

输入:

将中缀表达式存于文本文件中,程序从该文本文件中读出表达式。

输出:

如果该中缀表达式正确,则将后缀表达式输出到该文件中原表达式的后面,它们之间用“---”后相连;如果不正确,请在输出表达式错误提示到该文件原表达式的后面,它们之间用“---”相连。

(2)利用堆栈来实现中缀表达式转换为后缀表达式。

测试用例

输入:

21+23*(12-6)

输出:

2123126-*+

resultis159

课后习题

采用非递归的编程方法分别统计二叉树的节点个数度为1和叶子节点的个数以及数据值的最大值和最小值。

 

实验预习报告部分

HUNANUNIVERSITY

 

课程实习报告

 

题目:

四则运算表达式求值

学生姓名

学生学号

专业班级

指导老师李晓鸿

完成日期

一、需求分析

1.本程序要求首先输入一组数据进行四则运算,输入的数据是按照中缀表达式的结构输入的,完成初始化后,把中缀表达式转化为后缀表达式(逆波兰表达式)输出,同时输出计算结果。

输入举例:

21+23*(12-6)//正常的中缀表达式结构输入有数据,有+-*/()

21+(12-6)*23

25^12*1+2

2577//数据输入中不能留空格,两个数据中间必须是符合四则运算的数据(+-*/())

2.程序的功能将输入的中缀表达式转化为后缀表达式输出,同时输出计算结果;

3.程序的输出就是转化后的后缀表达式以及计算的结果,输出结果间用空格隔开;

输出举例:

接上

后缀表达式为:

2123126-*+//输出结果间用一个空格隔开

计算结果为:

159

后缀表达式为:

21126-23*+

计算结果为:

159

输入非法,程序结束!

输入非法,程序结束!

4.测试数据:

见上。

二、概要设计

抽象数据类型

中缀表达式的存入和读取是核心问题,计算只要用到两个临时的栈一个存操作数,一个存运算符。

利用二叉树,根节点存操作符,其他节点存操作数,利用二叉树的遍历可以方便的存入和读出操作数和运算符。

(后序遍历实现后缀表达式)二叉树的ADT与节点的ADT分开定义

ADTBinNode

数据对象:

整数

数据关系:

基本操作:

intval()//返回结点的数值

VoidsetVal(constElem&)//设置节点的值

inlineBinNode*left()const//获取左结点

inlineBinNode*right()const//获取右结点

voidsetLeft(Node*it)//设置左结点

voidsetRight(Node*it)//设置右结点

BoolisLeaf()//是叶子节点吗?

二叉树

ADTBinTree

数据对象:

BinNode

数据关系:

二叉树

基本操作:

BinTree(charexp[]);//利用字符串建树

voidpostOrderTraverse(Bintree*T,visit());//后序遍历

ADTStack

数据对象:

BinNode类型

数据关系:

线性关系

基本操作:

boolpush(constBinNode&item);

boolpop(BinNode&it);

booltopValue(BinNode&it);

intlength();const

算法的基本思想

初始化:

怎样把中缀表达式转为二叉树?

(1)输入表达式;

(2)对表达式做括号检测;

(3)利用栈的思想转化中缀表达式,最后得到完整二叉树;

提取表达式输出及计算:

利用后序遍历完成从二叉树中提取后缀表达式,按照逆波兰表达式计算过程,遇到操作数压栈,遇到操作符,栈中弹出两个操作数,做运算,结果压入栈,知道只剩下一个数据为止。

程序的流程

程序由四个模块组成:

(1)初始化模块:

完成中缀表达式的输入;

(2)转换建树模块:

中缀表达式建树,并利用后序遍历输出树。

(3)计算模块:

利用后缀表达式计算表达式;

(4)输出模块:

输出后缀表达式及计算结果。

三、详细设计

物理数据类型

算法的具体步骤

伪代码:

输入和括号粗略匹配:

while(i<100)

{

cin.get(c);//输入字符,可读入/n

ch[i++]=c;

if(c=='\n'){

ch[--i]='#';

break;

}//endif

}

i=0;

while(ch[i]!

='#')

{

if(ch[i]=='('&&ch[i+1]!

=')')

coutk++;

elseif(ch[i]=='('&&ch[i+1]==')')

{

coutk=1;

break;

}

elseif(ch[i]==')'&&ch[i-1]!

='(')

coutk--;

i++;

}

if(coutk<0||coutk>0)

{

cout<<"括号不匹配!

"<

exit(0);

}

建树:

算法利用两个临时的栈,一个存操作数,一个存操作符,检测到操作数,建立叶子节点,压入存入操作数栈,遇到操作符,存入操作符栈,每次存操作符时与前一个操作符做运算级别比较,若上一个操作符级别大,则弹出上一个操作符,同时弹出两个操作数建立二叉树,操作符做根节点,在把根节点压入操作数栈,括号做优先级最高处理,遇到右括号(前提是有了左括号和必要的运算式),操作符栈弹出,同时弹出两个操作数,建立二叉树,根节点压入操作数的栈。

BinTree:

:

BinTree(charexp[])//根据字符串exp的内容构建表达式树T

{

stackPTR;//存放表达式树中的节点指针

stackOPTR;//存放操作符

charop;

inti=0;

OPTR.push('#');

op=OPTR.top();

boolflag=true;

while(!

((exp[i]=='#')&&(OPTR.top()=='#')))

{

if(isdigit(exp[i]))

{

flag=true;

i+=CrtLeafNode(PTR,&exp[i]);//操作数,建立叶子节点并入栈PTR

}

elseif(exp[i]=='')

{

i++;

flag=true;

}

else

{

switch(exp[i])

{

case'(':

{

flag=true;

OPTR.push(exp[i]);

i++;break;

}

case')':

{

op=OPTR.top();OPTR.pop();

while(op!

='(')

{

flag=true;

CrtSubTree(PTR,op);//操作数栈建立分支节点

op=OPTR.top();OPTR.pop();

}//endwhile

i++;

break;

}

default:

//exp[i]是+-*/

while(!

OPTR.empty())

{

op=OPTR.top();

if(!

flag)

{

cout<<"不能有连续的两个运算符!

"<

exit(0);

}

if(Precede(op,exp[i])=='>')//操作符比较优先级

{

CrtSubTree(PTR,op);

OPTR.pop();

}

if(exp[i]!

='#')

{

OPTR.push(exp[i]);

i++;

flag=false;

}

break;

}

}

}

}

root=PTR.top();//返回树的根节点

PTR.pop();

}

后序遍历:

voidpostorder(BinNode*subroot,char*exp,int&count)

{

if(subroot!

=NULL)

{

postorder(subroot->left(),exp,count);

postorder(subroot->right(),exp,count);

for(inti=0;ilength();i++)

exp[count++]=subroot->setVal(i);

exp[count++]='';

}

};

最后输出exp这个字符串,就是逆波兰表达式。

计算:

按照存在字符串中的后缀表达式,遇到数字转换为double实数,压入栈,遇到操作符,栈中弹出两元素,同时做运算(/除数不能问0),结果压入栈,知道剩下最后一个数字为止;

voidevaluate(charch[],double&result)

{

SqStackS;//运算栈

inti;

i=0;

while(ch[i]!

='#'&&i<100)

{

if(isdigit(ch[i]))

{

i+=EvalValue(&ch[i],S);//转换实数,压栈;

}

elseif(ch[i]=='')

i++;

else

{

EvalExpr(ch[i],S);//弹栈,做相应的运算;

i++;

}

}

if(S.length()==1)

result=S.pop();

}

result为最后的结果

intEvalValue(char*ch,SqStack&S)

{

inti=0;

doubleresult=0;

chara;

a=ch[i];

while(isdigit(a))

{

result=10*result+(double)(a-48);

a=ch[++i];

}

S.push(result);

returni;

}

voidEvalExpr(charch,SqStack&S)

{

doubles1=0;

doubles2=0;

if(S.length()<2)

{

printf("\n表达式错误\n");

exit(0);

}

switch(ch)

{

case'+':

s1=S.pop();

s2=S.pop();

S.push(s2+s1);break;

case'-':

s1=S.pop();

s2=S.pop();

S.push(s2-s1);break;

case'*':

s1=S.pop();

s2=S.pop();

S.push(s2*s1);break;

case'/':

s1=S.pop();

s2=S.pop();

if(s1!

=0)

S.push(s2/s1);

else

{

cout<<"除数不能为0!

无结果!

"<

exit(0);

}

break;

default:

printf("error");

}

}

算法的时空分析

此算法利用栈和二叉树来实现,故次算法的的时间复杂度为O(N)

输入和输出的格式

输入

本程序可以将输入的中缀表达式转化为后缀表达式,并输出计算结果

请输入表达式。

回车表示结束

输出

逆波兰表达式为为:

表达式值为:

4、测试结果

5、实验心得

四则运算表达式存入栈中,考虑到的情况十分的复杂,运算符的优先级和括号的问题,还有各种意外情况的处理,括号的匹配,十分麻烦,不愧是做的最复杂的实验;

6、附录

EX_4.cpp

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

当前位置:首页 > 经管营销 > 经济市场

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

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