逆波兰式求值
c++逆波兰式计算

c++逆波兰式计算C++逆波兰式计算是一种基于后缀表达式的计算方法。
逆波兰式也称为后缀表达式,其中操作符位于操作数之后。
下面我会从多个角度来解释逆波兰式计算。
1. 逆波兰式的转换:将中缀表达式转换为逆波兰式的过程称为逆波兰式的转换。
这个过程可以通过使用栈来实现。
具体步骤如下:从左到右扫描中缀表达式的每个元素。
如果遇到操作数,则直接输出到逆波兰式。
如果遇到操作符,则与栈顶操作符比较优先级。
如果栈顶操作符优先级高于当前操作符,则将栈顶操作符输出到逆波兰式,然后将当前操作符入栈;否则将当前操作符入栈。
如果遇到左括号,则将其入栈。
如果遇到右括号,则将栈顶操作符输出到逆波兰式,直到遇到左括号。
左括号出栈,但不输出到逆波兰式。
扫描结束后,将栈中剩余的操作符依次输出到逆波兰式。
2. 逆波兰式的计算:逆波兰式计算是通过对逆波兰式进行求值来得到结果的过程。
这个过程同样可以使用栈来实现。
具体步骤如下:从左到右扫描逆波兰式的每个元素。
如果遇到操作数,则入栈。
如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。
扫描结束后,栈中的唯一元素即为最终的结果。
3. C++实现逆波兰式计算:在C++中,可以使用栈来实现逆波兰式的计算。
具体步骤如下:定义一个栈来存储操作数。
从左到右扫描逆波兰式的每个元素。
如果遇到操作数,则将其转换为数字并入栈。
如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。
扫描结束后,栈中的唯一元素即为最终的结果。
总结:逆波兰式是一种基于后缀表达式的计算方法,可以通过转换中缀表达式得到。
逆波兰式计算可以使用栈来实现,通过扫描逆波兰式的每个元素,根据操作数和操作符进行相应的操作,最终得到计算结果。
在C++中,可以使用栈来实现逆波兰式的计算。
希望以上解释能够满足你的需求。
逆波兰表达式

问题背景表达式求值是程序设计语言编译中的一个最基本的问题.因为任何程序设计语言都必须具有表达式求值的功能,同时表达式的计算应用也相当广泛,比如电力调度系统中的计算遥测、车站票务系统中的票价类型计算公式等。
通常,我们所说的表达式是由运算符、操作数、界限符所组成。
而算术表达式中最常见的表示法形式有中缀、前缀和后缀表示法。
中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。
1、中缀表达式———将运算符放在两操作数的中间。
在运算中存在运算符的优先权与结合性的问题。
例如运算:a*b+(c-d/e)*f 时,编译器即自左向右逐一检查,当检查到第一个运算符“*”时还无法知道是否执行;待检查到第二个运算符“ + ”时,因为知道“*”的优先级别高于“ + ”时,才知道执行“a*b”;当继续检查到“ ( ”时,可知道先执行括号以内部分等。
2、前缀表达式———将运算符放在两操作数的前面。
这种表示法经常用于计算机科学,特别是编译器设计方面。
为纪念其发明家—Jan Lukasiewicz,这种表示法也称波兰表示法。
3、后缀表达式———将运算符放在两操作数的后面。
后缀表达式也称逆波兰表达式,因其使表达式求值变得轻松,所以被普遍使用。
前缀和后缀表示法有三项公共特征:(1)操作数的顺序与等价的中缀表达式中操作数的顺序一致(2)不需要括号(3)操作符的优先级不相关题目描述读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确,并输出相关信息一、需求分析1、输入的形式和输入值得范围:输入一后缀表达式,相邻项之间以空格隔开,以#为结束标志,操作数为实数,操作符为+ - * / ;2、输出的形式:如果表达式正确则输出表达式的计算结果,若不正确则输出错误提示3、程序的功能:从键盘读入一后缀表达式(操作数是实数),如果表达式正确输出表达式的计算结果,如果表达式错误,则输出错误提示。
4、测试数据:样例1:输入: 2.5 3 * 5 - 3 + #(正确的输入)输出:************************运算结果是5.5样例2:输入: 2.5 3 * 3 - + #(错误的输入)输出:表达式错误!************************并弹出错误提示:二、概要设计1、抽象数据类型:为实现以上功能,根据题目要求,采用链式栈来存储表达式的操作数,数据成员top用来指向链式栈第一个节点(栈顶),变量element用来存储栈顶节点的值,变量size用来记录当前栈的大小链式栈的基本操作:Lstack(int size = 0,sNode* top=NULL);//栈的构造函数void Insert(double a);//向栈中插入一元素double pop();//取出栈顶元素int GetSize(){ return size;}//返回当时栈的大小计算表达式的函数:void Compute();2、算法的基本思想:(1)成员Insert(double a )首先建立一新的节点并修改新产生的节点的next域指向栈顶,然后设置top指向新的链表节点,并把size的值加1(2)成员pop()中如果栈的大小大于1,则返回栈顶元素,变量tos 用来记录栈顶元素,p用来指向当前的栈顶节点,把top指向当前栈顶的下一个节点,然后释放p指向的节点,同时size减1,返回tos;如果栈的大小小于1,则抛出一整型异常(3)函数Compute()中建立了链式栈s,并定义double 类型的变量x,y,字符类型的变量a。
后缀表达式的实现(逆波兰表达式)

课程名称:编译原理实验项目:后缀表达式的实现姓名:专业:班级:学号:计算机科学与技术学院20 年月日实验名称:消去C程序中的注释一、实验目的1、为了更好的配合《编译原理》有关词法分析章节的教学。
2、加深和巩固学生对于词法分析的了解和掌握。
3、使学生通过本实验能够初步的了解和掌握程序词法分析的整个过程。
4、提高学生的上机和编程过程中处理具体问题的能力。
二、实验要求设计、编制并调制一个程序,将中缀表达式改写为后缀表达式。
掌握中间语言的转换方法。
功能可以包括:1.后缀表达式求值后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。
假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。
3)读到8,将其直接放入栈中。
4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。
而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。
最后求的值288。
2.中缀表达式转后缀表达式规则:中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。
注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”,“*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。
弹出完这些元素后,才将遇到的操作符压入到栈中。
有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
逆波兰表达式求值

逆波兰表达式求值一.需求分析1.本程序读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要验证后缀表达式是否正确。
2.一个后缀表达式由用户通过键盘输入,对非法输入做处理,即假设输入有不合法的。
3.在dos界面输出运算结果。
4.测试数据输入2 3 * 1 -#输出5二.概要设计抽象数据类型为实现上述程序的功能,用户应输入的是后缀表达式。
算法的基本思想定义如下堆栈typedef struct{SElemtype * base;SElemtype * top;int stacksize;} SqStack;基本操作:Status InitStack(SqStack &S)创建一个堆栈iint StackLength(SqStack S) 堆栈已经存在,返回s中数据元素的个数Status Push(SqStack &S, SElemtype e)入栈操作Status Pop(SqStack &S, SElemtype &e) 出栈操作Status IsDigital(char ch) 判断输入的是数字还是字母int EvalValue(char *ch, SqStack &S) 把输入的表达式入栈,是字母就直接入栈,数字的话就要变为相应的整数void EvalExpr(char ch, SqStack &S) 进行运算的函数如果ch中保存的是操作符,则从堆栈中弹出两个元素,并把操作符应用在这两个元素之上,然后把操作结果压入到栈中。
如果试图从栈中弹出两个元素是,该栈中并没有,那么该后缀表达式是不正确的。
Status evaluate (char ch[], float & result)可判断正确性如果到达表达式末尾时,栈中剩余元素不止一个,那么该后缀表达式是不正确的。
再下面是一个主函数,调用各个函数,进行运算。
算法的基本思想利用堆栈先把表达式赋给一个数组(表达式为一个后缀表达式,两操作数之间用空格隔开最后一#字结束。
逆波兰表达式

逆波兰表达式逆波兰表达式表达式⼀般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,这称为中缀表达式(Infix Expression),如A+B。
波兰数学家Jan Lukasiewicz提出了另⼀种数学表⽰法,它有两种表⽰形式:把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;其中,逆波兰表达式在编译技术中有着普遍的应⽤。
算法:⼀、将中缀表达式转换成后缀表达式算法:1、从左⾄右扫描⼀中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存⼊操作数堆栈3、若读取的是运算符(1) 该运算符为左括号"(",则直接存⼊运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为⽌。
(3) 该运算符为⾮括号运算符:(a) 若运算符堆栈栈顶的运算符为括号,则直接存⼊运算符堆栈。
(b) 若⽐运算符堆栈栈顶的运算符优先级⾼或相等,则直接存⼊运算符堆栈。
(c) 若⽐运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压⼊运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
⼆、逆波兰表达式求值算法:1、循环扫描语法单元的项⽬。
2、如果扫描的项⽬是操作数,则将其压⼊操作数堆栈,并扫描下⼀个项⽬。
3、如果扫描的项⽬是⼀个⼆元运算符,则对栈的顶上两个操作数执⾏该运算。
4、如果扫描的项⽬是⼀个⼀元运算符,则对栈的最顶上操作数执⾏该运算。
5、将运算结果重新压⼊堆栈。
java逆波兰表达式求值

java逆波兰表达式求值一、什么是逆波兰表达式逆波兰表达式(Reverse Polish notation,简称RPN)是一种将运算符放在操作数后面的表达式表示方法。
例如,中缀表达式“2+3”可以写成逆波兰表达式“2 3 +”。
二、为什么要使用逆波兰表达式使用逆波兰表达式可以避免使用括号来区分优先级,使得计算机在计算时更加高效。
三、如何将中缀表达式转换为逆波兰表达式1. 创建一个栈S用于存储运算符。
2. 从左到右扫描中缀表达式的每个元素:(1)如果元素是数字,则直接输出。
(2)如果元素是运算符,则判断:a. 如果栈S为空或栈顶元素为左括号“(”,则将该运算符压入栈S中;b. 否则,比较该运算符与栈顶运算符的优先级:i. 如果该运算符优先级高于栈顶运算符,则将该运算符压入栈S中;ii. 否则,将栈顶元素弹出并输出,然后继续比较该运算符与新的栈顶元素的优先级。
(3)如果元素是左括号“(”,则将其压入栈S中。
(4)如果元素是右括号“)”,则依次弹出栈顶元素并输出,直到遇到左括号“(”,将左括号弹出但不输出。
3. 如果中缀表达式扫描完毕,则依次弹出栈中所有运算符并输出。
四、如何使用逆波兰表达式求值1. 创建一个栈S用于存储操作数。
2. 从左到右扫描逆波兰表达式的每个元素:(1)如果元素为数字,则将其压入栈S中。
(2)如果元素为运算符,则弹出栈顶的两个操作数进行运算,并将结果压入栈S中。
3. 如果逆波兰表达式扫描完毕,则栈S中只剩下一个数字,即为该表达式的计算结果。
五、Java实现逆波兰表达式求值可以通过使用Java的Stack类来实现上述算法。
具体步骤如下:1. 将中缀表达式转换为逆波兰表达式,得到一个字符串数组tokens。
2. 创建一个Stack<Integer>对象stack用于存储操作数。
3. 从左到右扫描tokens数组的每个元素:(1)如果元素为数字,则将其转换为整数并压入stack中。
中缀式到逆波兰式的转换及求值

号 等 ) 的 运 算 规 则 , 因 此 ,人 们 习 惯 用 中缀 式 对 于 运 算 的 实
现 ,特 别 是 计 算 机 或 计 算 器 的 实 现 来 说 ,实 际 上 是 比较 麻 烦 的。 同 样 ,在计 算 机 科 学 的 编译 领 域 中 。要 从 中缀式 直 接产 生 目标 代码 相 对 来 说 也 是 比较 麻 烦 的 。这 样 的 现 象 同样 体 现 在 一 些 财 务 或会 计 软 件 ( 工 资管 理 ) 中 。在 这 些 软 件 中 ,不 可避 如 免 地 都 要用 到公 式 的 定 义及 求 值 , 由于 财 务 、会 计计 算 中公 式 的复 杂 性 和 动 态 性 ,如 果 直 接用 中 缀 式 来 实 现 其 定 义 和 求 值 ,
表 1 中 缀式 、逆 波 兰 式对 照表
中缀式
a b + a b‘ + c
将 中缀 式 转换 成 逆 波 兰 式 并 进 行求 值 需 要 完 成 如 下 几 件工
作:
逆波兰式
a+ b a b* + c
( ) 对 中 缀 式 进 行 语 法 分 析 ( 的地 方 也 称 其 为 合 法 性 1 有
的运 算 的首 选 算法 。
逆 波 兰 式 不仅 能用 于 表 示 和 计 算 表 达式 .还 可 用 于 表 示 其
他 的语 法 结 构 ,此 时 的逆 波 兰 表 达 式 中 的运 算 符 不 再 仅仅 局 限
于算 术 运 算 符 、关 系运 算 符 和 逻辑 运算 符 ,而 且 ,每 个 运算 符
表 1是与 中缀 式对 应 的逆 波 兰 表示 。
另 外 ,逆 波 兰 式 的输 入 过 程 实 质 上 就 是 其 计 算 过 程 .因 此 ,可 以清 楚 地 看 到 整个 计 算 的 中间 结 果 。 它 的 这一 特 点 增 强 了交 互性 ,让 用 户 能够 在 运 算 的 过 程 中 方便 地发 现 和 改 正 运 算 错 误 ,并 且 还 能 很 好地 跟 踪 运 算 流 程 .动 态 地 自定义 运 算 过 程 中某 个 运 算 符 的 优 先 级 。在 1 7 9 2年 He l tP c ad公 司 发 现 we — akr t
逆波兰表达式求值

逆波兰表达式求值根据,求表达式的值。
有效的运算符包括 +, -, *, / 。
每个运算对象可以是整数,也可以是另⼀个逆波兰表达式。
说明:整数除法只保留整数部分。
给定逆波兰表达式总是有效的。
换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
⽰例 1:输⼊: ["2", "1", "+", "3", "*"]输出: 9解释: ((2 + 1) * 3) = 9⽰例 2:输⼊: ["4", "13", "5", "/", "+"]输出: 6解释: (4 + (13 / 5)) = 6⽰例 3:输⼊: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]输出: 22解释:((10 * (6 / ((9 + 3) * -11))) + 17) + 5= ((10 * (6 / (12 * -11))) + 17) + 5= ((10 * (6 / -132)) + 17) + 5= ((10 * 0) + 17) + 5= (0 + 17) + 5= 17 + 5= 22根据此题,掌握数据结构中栈的使⽤题⽬分析:逆波兰式也叫后缀表达式。
逆波兰式的定义可以goole查询。
那么怎样根据给出的逆波兰式转换为我们熟悉的中缀表达式来求值呢?这就需要运⽤到栈的知识:根据这个题⽬,我们扫描字符数组,当扫描到的字符是数字的时候,⼊栈;当扫描到的字符是运算符的时候,将栈中栈顶数字和与栈顶相连的数字出栈,最后栈顶元素就是表达式的结果,通过peek()操作就可以输出。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、需求分析
1.从键盘中输入一个后缀表达式,该表达式包括加减乘除等操作符,以及正整数做诶操作数等。
2.需要利用堆栈来实现。
3.在Visual C++6.0界面操作。
问题描述:
读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要校验后缀表达式是否正确。
测试数据用例
(1)输入:2 3 * 1 - #
输出:5
(2)输入:2 3 * 1 - * #
输出:表达式有误
(3)输入:2 0 / 4 * #
输出:表达式有误
二、概要设计
抽象数据类型
为实现上述程序的功能,则以字符型数据存储用户的输入。
若为数值,则用自定义函数将其转化为整形数据;若为操作符,则仍为字符型数据,以便计算出的结果。
算法的基本思想
根据题目要求,采用堆栈来实现。
该算法的基本思想是运用自定义函数求解逆波兰表达式求值问题问题。
程序的流程
程序由三个模块组成:
(1)输入模块:完成表达式的输入,存入栈S中。
(2)计算模块:利用自定义函数,计算逆波兰表达式的值。
(3)输出模块:屏幕上显示出最终计算结果。
三、详细设计
物理数据类型
程序中要求输入的表达式为任意的,但必须以#标志表达式输入的结束,只有正确的逆波兰表达式才能显示出最终计算结果。
算法的具体步骤
算法的具体步骤为:
建立一个名为s的栈。
将表达式的值一个个压入栈S中。
在循环中,需要分类讨论:如果表达式中的值为“#”,则将#前的元素弹出栈中;如果表达式中的值为空格,那么继续压入,如果表达式中的值为0至9的字符,则要通过一个自定义的转换函数将其转换为int型数值;如果连续几个0至9的字符中间无空格隔开,则在计算中应将其还原为多位数;若表达式中的值为运算符,则要将栈S中所压入数值弹出栈,进行相应的计算后,再将结果压入栈中(值得注意的是,运算符是不入栈的);除此之外的情况都归类为输入的表达式错误。
相应的入栈出栈及数值计算部分都由自定义函数来完成。
输入和输出的格式
输入
在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。
以“#”表示结束。
输出
如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。
四、调试分析
略。
(已在老师面前调试)
五、测试结果
六、实验心得(可选)
本次实验是我第一次接触用栈来编写的程序,发现自己对栈的定义及使用还是不够熟悉;发现自己的逻辑严密性不够,在今后的编程过程中要注意加强这方面的能力。
(这个C程序是老师给我们调试了两节课所得,并不是我做实验的程序,但是觉得这个程序给我印象更深刻,故写入实验报告。
)
七、附录(可选)
//用栈来实现逆波兰式求值问题
#include"stdio.h"
#include"stdlib.h"
#define STACK_INIT_SIZE 100//栈的存储空间初始分配
#define STACKINCREMENT 10// 存储空间分配增量
#define TRUE 1
#define False 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//相当于定义一个数据结构类型
typedef int SElemtype;
typedef struct
{
SElemtype *base;
int top;
int stacksize;
} SqStack;
Status InitStack(SqStack &S )
{
S.base = (SElemtype *)malloc(STACK_INIT_SIZE*sizeof(SElemtype));
if (! S.base) exit(OVERFLOW);
S.top = -1;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
int StackLength(SqStack S)
{
//获得堆栈元素的个数
return S.top+1;
}
Status Push(SqStack &S, SElemtype e)
{
//入栈
//填空
if(S.top ==99)
{//栈满
return ERROR;
}
S.base[++S.top] = e;
return OK;
}
Status Pop(SqStack &S, SElemtype &e)
{
//出栈
if(S.top==-1)return ERROR;
e=S.base[S.top--];
return OK;
}
Status IsDigital(char ch)
{
if(ch>='0'&&ch<='9')
{
return 1;
return 0;
}
int EvalValue(char *ch, SqStack &S)
{//将字符型数字转换为int型
int i=0;
SElemtype result=0;
char a;
a=ch[i];
while(IsDigital(a))
{
result=10*result+(int)(a-48);
a=ch[++i];
}
Push(S, result);
return i;
}
void EvalExpr(char ch, SqStack &S)
{
//如果ch中保存的是操作符,则从堆栈中弹出两个元素,并把操作符应用在这两个元素之上,然后把操作结果压入到栈中。
如果试图从栈中弹出两个元素是,该栈中并没有,那么该后缀表达式是不正确的。
SElemtype a,b;
Pop(S,a);
Pop(S,b);
switch(ch)
{
case '+':Push(S,a+b);break;
case '-':Push(S,b-a);break;
case '*':
Push(S,a*b);break;
case '/':if(a) Push(S,b/a);break;
default: printf("ERROR");
}
}
Status evaluate (char ch[], float & result)
{
SqStack S;
Status St;
int i;
i=0;
St = InitStack(S);
while(ch[i]!='#'&&i<100)
{
if(IsDigital(ch[i]))
{
i+=EvalValue(&ch[i], S);
}
else if(ch[i]==' ')
i++;
else{
EvalExpr(ch[i], S);
i++;
}
}
//如果到达表达式末尾时,栈中剩余元素不止一个,那么该后缀表达式是不正确的。
int a;
if(StackLength(S) ==1)
{
Pop(S,a);
result=(float)a;
}
else
{
printf("表达式错误");
return ERROR;
}
return OK;
}
main()
{
Status St;
char ch[100],c;
int i=0;
float result;
printf("请输入表达式。
#表示结束\n");
while(i<100)
{
scanf("%c",&c);
ch[i++]=c;
if(c=='#')
break;
}
ch[i] = '\0';
St = evaluate (ch, result);
if (St)
printf("result is %10.2f \n", result);
else
printf("\n表达式错误\n");
return 0;
}。