1、课程实习报告 题 目: 四则运算表达式求值 学生姓名 学生学号 专业班级 指导老师 李晓鸿 完 成 日 期 一、需求分析1本程序要求首先输入一组数据进行四则运算,输入的数据是按照中缀表达式的结构输入的,完成初始化后,把中缀表达式转化为后缀表达式(逆波兰表达式)输出,同时输出计算结果。输入举例: 21+23*(12-6)/正常的中缀表达式结构输入有数据,有+ - * /()21+(12-6)*232512*1+225 7 7/数据输入中不能留空格,两个数据中间必须是符合四则运算的数据(+-*/()2程序的功能将输入的中缀表达式转化为后缀表达式输出,同时输出计算结果;3程序的输出就是转化后的后缀表
2、达式以及计算的结果,输出结果间用空格隔开; 输出举例:接上 后缀表达式为: 21 23 12 6 - * + /输出结果间用一个空格隔开 计算结果为:159 21 12 6 - 23 * + 输入非法,程序结束!4测试数据: 见上。二、概要设计抽象数据类型 中缀表达式的存入和读取是核心问题,计算只要用到两个临时的栈一个存操作数,一个存运算符。利用二叉树,根节点存操作符,其他节点存操作数,利用二叉树的遍历可以方便的存入和读出操作数和运算符。(后序遍历实现后缀表达式)二叉树的ADT与节点的ADT分开定义ADT BinNode数据对象:整数数据关系:无基本操作:int val() /返回结点的数值
3、Void setVal(const Elem&)/设置节点的值 inline BinNode* left()const /获取左结点 inline BinNode* right()const /获取右结点 void setLeft(Node* it) /设置左结点 void setRight(Node* it) /设置右结点Bool isLeaf() /是叶子节点吗?二叉树ADT BinTreeBinNodeBinTree(char exp);/利用字符串建树void postOrderTraverse(Bintree*T,visit(); /后序遍历 ADT StackBinNode类型线性
4、关系bool push(const BinNode&item);bool pop(BinNode&it);bool topValue(BinNode&int length();const算法的基本思想初始化:怎样把中缀表达式转为二叉树? (1)输入表达式; (2)对表达式做括号检测; (3) 利用栈的思想转化中缀表达式,最后得到完整二叉树;提取表达式输出及计算:利用后序遍历完成从二叉树中提取后缀表达式,按照逆波兰表达式计算过程,遇到操作数压栈,遇到操作符,栈中弹出两个操作数,做运算,结果压入栈,知道只剩下一个数据为止。程序的流程程序由四个模块组成:(1) 初始化模块:完成中缀表达式的输入;(2
5、) 转换建树模块:中缀表达式建树,并利用后序遍历输出树。(3) 计算模块:利用后缀表达式计算表达式; (4)输出模块:输出后缀表达式及计算结果。三、详细设计物理数据类型算法的具体步骤伪代码:输入和括号粗略匹配:while(i100) cin.get(c);/输入字符,可读入/n chi+=c; if(c=n) ch-i=#; break; /end if i=0; while(chi!=) if(chi=(&chi+1!) coutk+; else if(chi=chi+1= coutk=1; chi-1! coutk-; i+; if(coutk0) cout括号不匹配!endl; exit
6、(0); 建树:算法利用两个临时的栈,一个存操作数,一个存操作符,检测到操作数,建立叶子节点,压入存入操作数栈,遇到操作符,存入操作符栈,每次存操作符时与前一个操作符做运算级别比较,若上一个操作符级别大,则弹出上一个操作符,同时弹出两个操作数建立二叉树,操作符做根节点,在把根节点压入操作数栈,括号做优先级最高处理,遇到右括号(前提是有了左括号和必要的运算式),操作符栈弹出,同时弹出两个操作数,建立二叉树,根节点压入操作数的栈。BinTree:BinTree(char exp)/根据字符串exp的内容构建表达式树T stack PTR;/存放表达式树中的节点指针char OPTR;/存放操作符
7、char op; int i=0; OPTR.push(); op = OPTR.top(); bool flag=true; while( !(expi=) & (OPTR.top()=) ) if (isdigit(expi) flag=true; i+=CrtLeafNode(PTR, &expi);/操作数,建立叶子节点并入栈PTR else if (expi = i+; else switch (expi) case flag=true; OPTR.push(expi); i+;break; op = OPTR.top(); OPTR.pop(); while(op! flag=tr
8、ue; CrtSubTree(PTR, op);/操作数栈 建立分支节点 op = OPTR.top(); /end while break; default: /expi是+ -* / while(! OPTR.empty() if(!flag) cout)/操作符比较优先级 OPTR.pop(); if(expi! OPTR.push(expi); i+; flag=false; root= PTR.top();/返回树的根节点 PTR.pop();后序遍历:void postorder(BinNode* subroot,char *exp,int &count) if (subroot
9、!= NULL) postorder(subroot-left(),exp,count);right(),exp,count); for(int i=0;ilength();i+) expcount+ = subroot-setVal(i); expcount+ = ;最后输出exp这个字符串,就是逆波兰表达式。计算:按照存在字符串中的后缀表达式,遇到数字转换为double实数,压入栈,遇到操作符,栈中弹出两元素,同时做运算(/除数不能问0),结果压入栈,知道剩下最后一个数字为止;void evaluate(char ch, double&result) SqStack S;/运算栈 int
10、i; if(isdigit(chi) i+=EvalValue(&chi, S); /转换实数,压栈; EvalExpr(chi, S); /弹栈,做相应的运算; if(S.length() =1) result=S.pop();result为最后的结果int EvalValue(char*ch, SqStack&S) double result=0; char a; a=chi; while(isdigit(a) result=10*result+(double)(a-48); a=ch+i; S.push(result); return i;void EvalExpr(char ch, S
11、qStack& double s1=0; double s2=0; if(S.length()2) printf(n表达式错误n switch(ch) case + s1=S.pop(); s2=S.pop(); S.push(s2+s1);- S.push(s2-s1);* S.push(s2*s1);/ if(s1!=0) S.push(s2/s1); cout除数不能为0!无结果! default:printf(error算法的时空分析此算法利用栈和二叉树来实现,故次算法的的时间复杂度为O(N)输入和输出的格式输入本程序可以将输入的中缀表达式转化为后缀表达式,并输出计算结果请输入表达式。回车表示结束 输出逆波兰表达式为为:表达式值为:4、测试结果5、实验心得四则运算表达式存入栈中,考虑到的情况十分的复杂,运算符的优先级和括号的问题,还有各种意外情况的处理,括号的匹配,十分麻烦,不愧是做的最复杂的实验;6、附录EX_4.cpp
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1