逆波兰式求值

合集下载

c++逆波兰式计算

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逆波兰表达式求值

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()操作就可以输出。

中缀表达式转逆波兰式并求值

中缀表达式转逆波兰式并求值

中缀表达式转逆波兰式并求值// 标题: 栈的应用——中缀表达式转逆波兰式 // 时间: 2015年4月14日// 所有者: Vae#include<stdio.h>#include<malloc.h>#include<stdlib.h>#include<windows.h>#include<Winuser.h>#define STACK_INIT_SIZE 100 #define STACKCREATE 10 #define OK 1 #define ERROR 0typedef struct double_stack {int *num;int *index;}DOUBLESTACK;typedef struct SqStack{DOUBLESTACK top; DOUBLESTACK base;int stacksize;}SqStack;// 函数名: InitStack // 形参类型: SqStack * // 函数功能构造一个栈void InitStack(SqStack *S) {S->base.index = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);S->base.num = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);if (!(S->base.num && S->base.index)){printf("构造栈失败!\n");exit(-1);}S->top.num = S->base.num;S->top.index = S->base.index;S->stacksize = STACK_INIT_SIZE;return ;}// 函数名: Push// 形参类型: SqStack *, int, int // 函数功能插入e为新的栈顶元素int Push(SqStack *S, int m, int n){if ((S->top.num - S->base.num) >= S->stacksize){S->base.index = (int *)realloc(S->base.index,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE));S->base.num = (int *)realloc(S->base.num,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE));if (!(S->base.num || S->base.index))return ERROR; }*S->top.index++ = n;*S->top.num++ = m;S->stacksize = S->stacksize + STACKCREATE;return OK;}// 函数名: Pop// 形参类型: SqStack *, int *, int * // 函数功能出栈并用e返回int Pop(SqStack *S, int *a, int *b) {if (S->base.num == S->top.num) return ERROR;*a = * --S->top.num;*b = * --S->top.index;return OK;}// 函数名: GetTop// 形参类型: SqStack *, int * // 函数功能用e返回栈顶元素int GetTop(SqStack S, int *e) {if (S.top.num == S.base.num)return ERROR;*e = *(S.top.num - 1);return OK;}// 函数名: EmptyStack // 形参类型: SqStack// 函数功能判断是否为空栈int EmptyStack(SqStack S) {if (S.base.num == S.top.num)return OK;elsereturn ERROR;}// 函数名: Precede// 形参类型: char, char// 函数功能判断运算符的优先关系char Precede(char t1, char t2) { char f;switch(t2){case '+':case '-':if(t1=='(' || t1=='\n')f = '<'; //t1<t2elsef = '>'; // t1>t2break;case '*':case '/':if (t1=='*' || t1=='/' || t1==')') f = '>';elsef = '<';break;case '(':if (t1 == ')'){printf("括号不匹配\n");exit(-1);}elsef = '<';break;case ')':switch(t1){case '(': f = '=';break;case '\n': printf("缺乏左括号\n"); exit(-1); default:f = '>';}break;case '\n':switch(t1){case '\n':f = '='; break; case '(':printf("缺乏右括号\n");exit(-1);default:f = '>'; }}return f;}// 函数名: In// 形参类型: char // 函数功能判断是否为7种运算符之一int In(char c){switch(c){case '+' :case '-' :case '*' :case '/' :case '(' :case ')' :case '\n': return OK;default : return ERROR;}}// 函数名: ShowStack // 形参类型: SqStack // 函数功能输出表达式的逆波兰式void ShowStack(SqStack S) {int a, b;SqStack q;InitStack(&q);while (!EmptyStack(S)){Pop(&S,&a,&b);Push(&q,a,b);}printf("原表达式转换成逆波兰式为\n"); while (!EmptyStack(q)){Pop(&q,&a,&b);if (b == 0)printf("%c ", a);elseprintf("%d ", a);}printf("\n");}// 函数名: Opertae // 形参类型: int, char, int // 函数功能做四则运算 a theta bint Operator_(int a, char theta, int b){switch(theta){case '+':return a+b; case '-':return a-b;case '*':return a*b;}return a/b;}// 函数名: GetValue // 形参类型: SqStack// 函数功能求的表达式的值void GetValue(SqStack S) {int a, b;SqStack q,p;int value;int m, n;int c, d;char z;InitStack(&q);InitStack(&p);while (!EmptyStack(S)) {Pop(&S,&a,&b);Push(&q,a,b); }while (!EmptyStack(q)) {Pop(&q,&a,&b);if (b == 0){Pop(&p,&m,&c);Pop(&p,&n,&d);z = toascii(a);value = Operator_(n,z,m); Push(&p,value,1);}elsePush(&p,a,1);}Pop(&p,&a,&b);printf("表达式的值为:%d\n", a);return ;}// 函数名: EvaLuateExpression // 形参类型: void// 函数功能得到逆置的后缀表达式void EvaluateExpression(){SqStack OPRT, OPND; // 设OPTR 和 OPND 分别为运算符栈和运算数栈d, x; charint y;char c;char z[11];int i;InitStack(&OPRT);InitStack(&OPND);Push(&OPRT,'\n',0); //将换行符压入运算符栈的栈底c = getchar();GetTop(OPRT,&x);//将运算符栈OPTR的栈顶元素赋值给xwhile (c!='\n' || x!='\n'){if (In(c)) //c是7种运算符之一{switch(Precede(x,c)) //判断x和c的优先级 {case '<':Push(&OPRT,c,0);c = getchar();break; case '=':Pop(&OPRT,&x,&y);c=getchar();break;case '>':Pop(&OPRT,&x,&y);Push(&OPND,x,y);}}else if (c>='0' && c<='9'){i = 0;while (c>='0' && c<= '9') {z[i++] = c;c = getchar(); }z[i] = '\0';d = atoi(z); //将z中保存的数值型字符窜转化为整型存于d中 Push(&OPND,d,1);}else{printf("出现非法字符!\n");exit(-1);}GetTop(OPRT,&x);}ShowStack(OPND);GetValue(OPND);}int main(void){printf("请输入表达式,负数用(0-正数)表示:"); EvaluateExpression();return 0;}。

写出下列逆波兰式的中缀表达式

写出下列逆波兰式的中缀表达式

写出下列逆波兰式的中缀表达式
逆波兰式:
A B + C D E - × /
中缀表达式:
(A + B) / (C - D × E)
今天,我们要来聊聊数学运算中有关逆波兰式的内容。

一般而言,逆波兰式(Reverse Polish Notation,RPN)也叫波兰式,是一种由波兰数学家所发明的数学表达式求值方法。

它将操作符置于操作数之后,然后形成一个序列。

它可以帮助我们简化一些数学表达式的计算方式,从而更加高效率地完成计算工作。

比如,上面提到的逆波兰式: A B + C D E - × /,可以重新排列为中缀表达式: (A + B) / (C - D × E),它的意思就是 A 与 B 相加,然后除以 C 减去 D 乘以 E 的结果。

那么,为什么我们要使用逆波兰式呢?最主要的一个原因是,它比起使用括号的中缀表达式更加简洁易读。

另外,它也具有计算时间上的优势。

这是由于它不需要进行括号匹配和优先级解析,因此可以更快地完成计算。

在程序开发中,使用逆波兰式也十分常见。

它可以帮助我们对一些复杂的数学表达式更加高效地进行计算。

尤其是当计算的数据量很大时,使用逆波兰式可以大大提高计算速度。

总而言之,逆波兰式可以让我们更加准确地表达数学式,同时具备更快的计算效率。

逆波兰表达式求解

逆波兰表达式求解

逆波兰表达式求值问题描述:后缀表达式———将运算符放在两操作数的后面。

后缀表达式也称逆波兰表达式,因其使表达式求值变得轻松,所以被普遍使用。

读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。

基本要求(1)从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。

(2)用堆栈来实现需求分析:1、输入形式:将后缀表达式存于文本文件中,其中后缀表达式中两相邻操作数之间利用空格隔开,程序从该文本文件中读出表达式。

2、输出形式:如果该后缀表达式正确,则计算结果,计算结果保留小数点后面两位有效数字,同时将结果输出到该文件中原表达式的后面,结果与表达式之间用“=”后相连;如果不正确,请在输出表达式错误提示到该文件原表达的后面,它们之间用“---”相连。

表达式中操作数为一实数,该实数精到小数点后面两位有效数字。

3、功能描述:a、判断所输入的后缀表达式是否合法b、如果合法则求解后缀表达式的值(精确到小数点后两位数字)4、样例输入输出(数据加强版)输入:42 3 * 1 –#2 3 * 0 / #2 3 * - #2 3 1 - #输出:5.00Error!Error!Error!抽象数据类型(ADT):后缀表达式求值可以用堆栈来实现!抽象数据结构类型描述:Typedef struct{Char st[MaxSize]; //存放栈中元素Int top; //栈顶指针}Stack;顺序栈的基本操作:V oid InitStack(Stack &s) function:置空栈Int push(Stack &s,char x) function:将元素x压入栈中Int gettop(Stack &s,char x) function:将栈顶元素的值赋给x,栈指针不变V oid pop(Stack &s,char x) function:将栈顶元素赋给x,栈指针递减Bool stackempty(Stack &s) function:判断栈是否为空栈概要设计:这就是一个基于数据结构栈的基本简单的操作,每次读入一个字符,当读入的为整数的时候,将其进栈,读入的为运算符的时候进行相应的运算,遇到'#'的时候,终止操作即可。

逆波兰式计算

逆波兰式计算

1.颠倒数组用递归的算法把数组中的N个数的次序重新存放后输出。

2.逆波兰式由键盘输入一个算术表达式,求出它的逆波兰式,并输出数值。

例:((3+4)*3+15)/3 的逆波兰式为3 4 + 3 * 15 + 3 /计算结果为12const m=100;type stack=array[1..m] of integer;var s:stack;a:string;t,i,j,k,len:integer;procedure push(x:integer);{进栈}begint:=t+1;s[t]:=x;end;function pop:integer;{出栈}beginpop:=s[t];t:=t-1;end;beginreadln(a); {读入后缀表达式}len:=length(a);i:=1; {后缀表达式字符指针初始化}t:=0; {栈初始化}while i<=len do {处理后缀表达式,直至结束}begincase a[i] of'0'..'9':begink:=0;while a[i]<>’.’ dobegin {从s中取出一个完整的操作数k}k:=10*k+ord(a[i])-48;i:=i+1;end;push(k);{把k压栈}end;'+':push(pop+pop);{从栈s中取出栈顶的两个数进行加法运算,然后将结果在压栈}'-':begin {从栈s中取出栈顶的两个数进行减法运算,然后将结果在压栈}j:=pop;push(pop-j);end;'*':push(pop*pop);{从栈s中取出栈顶的两个数进行乘法运算,然后将结果在压栈}'/':begin {从栈s中取出栈顶的两个数进行除法运算,然后将结果在压栈} j:=pop;push(pop div j);end;end;{case}i:=i+1;end;{while}writeln(pop); {取出栈顶元素,即时表达式的最后结果}end.。

逆波兰表达式求值算法

逆波兰表达式求值算法

逆波兰表达式求值算法逆波兰表示法(Reverse Polish Notation,RPN)是一种数学表达式表示法,它不需要括号来明确操作符的优先级。

在这种表示法中,操作符跟在操作数后面。

下面是一个逆波兰表达式的求值算法:1. 初始化一个堆栈用于存储数字。

2. 从左到右读取表达式中的每个字符。

3. 如果字符是一个数字,则将其转换为对应的数值,并压入堆栈。

4. 如果字符是一个操作符(例如加号、减号、乘号或除号),则从堆栈中弹出两个操作数,进行相应的运算,并将结果压回堆栈。

5. 重复步骤2-4,直到表达式结束。

6. 最后,堆栈中剩下的唯一元素就是表达式的计算结果。

下面是一个使用 Python 实现逆波兰表达式求值算法的示例代码:```pythondef eval_rpn(expression):stack = []operators = set('+-/')for token in ():if token not in operators:(int(token))else:y = ()x = ()if token == '+':(x + y)elif token == '-':(x - y)elif token == '':(x y)else: token == '/'(x // y) 使用整数除法,因为逆波兰表达式通常用于整数运算 return stack[0]```使用示例:```pythonexpression = "2 3 + 4 " 计算 (2 + 3) 4 的结果,即 20 result = eval_rpn(expression)print(result) 输出:20```。

表达式求值算法

表达式求值算法

表达式求值算法表达式求值算法是计算机科学中的重要概念之一,用于计算数学表达式的结果。

在编程语言中,表达式求值是一项基本的操作,并且经常在计算过程中需要用到。

本文将介绍一些常见的表达式求值算法及其实现。

1. 逆波兰表达式法逆波兰表达式法是一种用于计算数学表达式的算法,它使用后缀表达式(也称为逆波兰表达式)来表示表达式。

逆波兰表达式是将操作符放在操作数之后的一种表示方法。

对于任意一个数学表达式,都可以通过将中缀表达式转换为后缀表达式,然后使用栈结构计算得到结果。

逆波兰表达式法的优点是计算顺序明确,不需要考虑运算符的优先级和括号的处理。

2. 中缀表达式转后缀表达式法中缀表达式是我们常见的数学表达式,如 3 + 4 * 5。

在中缀表达式中,操作符的优先级和括号起着很大的作用。

为了将中缀表达式转换为后缀表达式,我们需要使用到栈结构。

具体的算法如下:- 遍历中缀表达式的每个元素。

- 如果是操作数,则直接输出。

- 如果是操作符,则判断其与栈顶操作符的优先级,决定是否将其压入栈。

- 如果是左括号,则直接压入栈。

- 如果是右括号,则依次弹出栈顶操作符,并输出,直到遇到左括号为止。

- 遍历完表达式后,如果栈不为空,则依次弹出栈顶操作符,并输出。

3. 后缀表达式求值法后缀表达式(逆波兰表达式)的求值方法相对简单。

我们可以使用栈结构来计算后缀表达式的结果。

具体的算法如下:- 遍历后缀表达式的每个元素。

- 如果是操作数,则将其压入栈。

- 如果是操作符,则弹出栈顶的两个操作数,执行相应的计算,并将结果压入栈。

- 遍历完后缀表达式后,栈中最后剩下的元素即为计算结果。

4. 二叉树表示法除了逆波兰表达式法和中缀表达式法,我们还可以使用二叉树来表示表达式,并通过遍历二叉树来计算表达式的结果。

具体的算法如下:- 构建二叉树,将表达式的操作符作为根节点,将操作数作为叶节点。

- 通过后序遍历二叉树,计算出每个子树的值,并将结果返回给其父节点。

逆波兰式的产生及计算

逆波兰式的产生及计算

实验六逆波兰式的产生及计算一、实验目的:将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。

二、实验预习提示1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。

用这种表示法表示的表达式也称做后缀式。

逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。

采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。

2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。

(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

(4)如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。

如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。

倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。

(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

3、逆波兰式计算的实验设计思想及算法(1)构造一个栈,存放运算对象。

(2)读入一个用逆波兰式表示的简单算术表达式。

(3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。

若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。

如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。

(4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。

逆波兰式

逆波兰式

定义逆波兰式也叫后缀表达式(将运算符写在操作数之后)如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+(a+b)*c-(a+b)/e的后缀表达式为:(a+b)*c-(a+b)/e→((a+b)*c)((a+b)/e)-→((a+b)c*)((a+b)e/)-→(ab+c*)(ab+e/)-→ab+c*ab+e/-算法实现将一个普通的中序表达式转换为逆波兰表达式的一般算法是:1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。

(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

(4)如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。

如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。

倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。

(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

逆波兰式的作用对于实现逆波兰式算法,难度并不大,但为什么要将看似简单的中序表达式转换为复杂的逆波兰式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。

相对的,逆波兰式在计算机看来却是比较简单易懂的结构。

因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。

下面以(a+b)*c为例子进行说明:(a+b)*c的逆波兰式为ab+c*,假设计算机把ab+c*按从左到右的顺序压入栈中,并且按照遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果再入栈的原则来进行处理,那么ab+c*的执行结果如下:1)a入栈(0位置)2)b入栈(1位置)3)遇到运算符“+”,将a和b出栈,执行a+b的操作,得到结果d=a+b,再将d 入栈(0位置)4)c入栈(1位置)5)遇到运算符“*”,将d和c出栈,执行d*c的操作,得到结果e,再将e入栈(0位置)经过以上运算,计算机就可以得到(a+b)*c的运算结果e了。

数据结构实验报告——逆波兰表达式求值

数据结构实验报告——逆波兰表达式求值

实验三逆波兰表达式求值一.问题描述:读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。

二.需求分析:1. 本程序需要基于堆栈的基本操作来实现逆波兰表达式的求值。

2.若表达式正确,界面自动输出后缀表达式的值,否则输出表达式错误的信息,将结果置为0。

3.操作数和操作符均由键盘键入。

4.输入输入一个后缀表达式2 3 * 1 - #输出结果5三.概要设计由于操作的事一串字符,所以首先选择一个字符数组存储该串字符,直接使用编译器自带的字符数组。

由于计算后缀表达式时,具有先进后出的规律,故而考虑使用堆栈其ADT Stack{操作对象:字符,整数,浮点数基本操作:Stack(int size);//构造大小为size的堆栈~Stack();//撤销堆栈Bool IsEmpty();//是否为空,是返回true,否则返回falseBool IsFull();//是否为满,是返回true,否则返回falseVoid Push(T X);//将x压入堆栈Void Pop(T &x);//弹出栈顶元素,并用x保存对于计算后缀表达式的值的算法:首先假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中,如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,直到最后一个字符为止。

对于表达式错误:返回01、小数缺少整数部分:如 .999未检测到数,而是直接检测到小数点2、运算符过多:2 3*-弹出一个数后堆栈便空3、运算数过多:3 7*0最后堆栈不空四.源程序:/*Name: 逆波兰表达式求值Copyright: WCH466-Experiment-3Author: wch466Date: 02/04/12 22:59Description: 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。

*/// Copyright: WCH466-Experiment-3#include<iostream>#include<string>#include<cmath>using namespace std;class Astack{private:int size;int top;float *list;bool g;public:Astack(int se=4){size=se;top=0;list=new float [size];g=1;}~Astack() {delete [] list;}void push(const float& it) //入{if(top==size) return;list[top++]=it;}float pop(){if(top==0) {g=0;return 0;} //g=0代表表达式错误(运算符多了)return list[--top];}bool judge(){return g;}int length() const {/*cout<<"length of list is "<<top<<endl; */return top;}};// Copyright: WCH466-Experiment-3void Pretreatstr(const char *a) //预处理字符{ int i=0,g=1,s=1,size=strlen(a),k=0;float num=0,in=0,x,y,de=0; //stand for integer,decimalAstack t(size);for(i=0;i<size;i++){ if(a[i]=='#') break;if(a[i]>47){ s=1; //有数if(g)in=in*10+a[i]-48; //提取整数部分else //小数处理{ de=(a[i]-48)*pow(0.1,k++)+de;}}if(a[i]==46){if(g==0) {cout<<"小数点多余!";return ;} g=0;k=1;} //有小数if(a[i]==42||a[i]==43||a[i]==45||a[i]==47||a[i]==' '){if(s) // s=0 代表没数{t.push(in+de);in=0;de=0;g=1;s=0;}/*cout<<"插入:"<<in+de<<endl;*/ if(a[i]!=' ') { y=t.pop(); x=t.pop();}if(a[i]=='+') t.push(x+y);if(a[i]=='-') t.push(x-y);if(a[i]=='*') t.push(x*y);if(a[i]=='/') {if(y==0) {cout<<"分母为零!"<<endl; return;} t.push(x/y); }}}if(t.length()==1&&t.judge()&&a[i-1]<48) //最后一个字符不能为num{ cout<<"表达式的答案是:"<<int(t.pop()*100)/100.0<<endl;}elsecout<<"表达式错误"<<endl;};// Copyright: WCH466-Experiment-3int main(){char s[100];while(gets(s))Pretreatstr(s);system("pause");return 0;}五.测试结果:六.实验心得:1. 通过本次试验,我发现自己分析问题不是很全面,忽略掉一些细节。

逆波兰式的产生与计算培训资料

逆波兰式的产生与计算培训资料
case '*': //字符为 * 时,
case '/': //字符为 /时, while(stack[top]=='*'||stack[top]=='/')
收集于网络,如有侵权请联系管理员删除
{ ex[t]=stack[top]; top--; t++;
} top++; stack[top]=ch; break;
while(top!=0) {
ex[t]=stack[top];// 在栈中元素中加上后面的符号
t++; top--; } ex[t]='#';
收集于网络,如有侵权请联系管理员删除
精品文档
n"); printf(" 原来表达式: "); for(j=1;j<sum;j++) printf("%c",str[j]);
收集于网络,如有侵权请联系管理员删除
精品文档
代码: #include<stdio.h> #include <stdlib.h> #include<math.h> #define max 100 char ex[max];//ex[] 数组用来存放逆波兰式 void trans() { char str[max]; char stack[max]; //存表达式的符号 char ch; int sum,i,j,t,top=0; printf("* 请输入一个求值的表达式,以 #结束 :\n"); printf("********************************************************** \n"); printf(" 您的算数表达式为: "); i=0; //进行初始化,从键盘输入表达式 do { i++; scanf("%c",&str[i]);// 从键盘输入的字符装入字符数组 str[] 中

数据结构——逆波兰式

数据结构——逆波兰式

数据结构——逆波兰式很久没有关注算法和数据结构,⼤部分知识都已经忘记了;是时间好好回炉⼀下了,说实话⼲读数据机构这本书还是挺枯燥⽽且这本书原理性⽐较多,有⼀定的难度。

这不刚看到逆波兰式废了好⼤劲才搞懂,⽼了。

逆波兰式逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)⼀个E的后缀形式可以如下定义:(1)如果E是⼀个变量或,则E的是E本⾝。

(2)如果E是E1 op E2形式的表达式,这⾥op是如何⼆元操作符,则E的后缀式为E1'E2' op,这⾥E1'和E2'分别为E1和E2的后缀式。

(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。

如:我们平时写a+b,这是,写成就是:ab+(a+b)*c-(a+b)/e的后缀表达式为:(a+b)*c-(a+b)/e→((a+b)*c)((a+b)/e)-→((a+b)c*)((a+b)e/)-→(ab+c*)(ab+e/)-→ab+c*ab+e/-算法实现将⼀个普通的中序转换为的⼀般算法是:⾸先需要分配2个栈,⼀个作为临时存储运算符的栈S1(含⼀个结束符号),⼀个作为输⼊逆波兰式的栈S2(空栈),S1栈可先放⼊优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。

可指定其他字符,不⼀定⾮#不可。

从中缀式的左端开始取字符,逐序进⾏如下步骤:(1)若取出的字符是,则分析出完整的运算数,该操作数直接送⼊S2栈(2)若取出的字符是,则将该运算符与S1栈栈顶元素⽐较,如果该(不包括括号运算符)⼤于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送⼊S2栈中,直⾄S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送⼊S1栈。

(3)若取出的字符是“(”,则直接送⼊S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个,依次送⼊S2栈,此时抛弃“(”。

波兰算法求二叉树表达式的值

波兰算法求二叉树表达式的值

逆波兰表达式问题描述逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。

逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4。

本题求解逆波兰表达式的值,其中运算符包括+ - * / 四个。

输入数据输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数输出要求输出为一行,表达式的值。

输入样例* + 11.0 12.0 + 24.0 35.0输出样例1357.000000#include <stdio.h>#include <stdlib.h>#include "string.h"struct node{char data[20];node *lChild,*rChild;};int k=0;doubleCalculateEepress(node *root){k++;if(root->data[0]>='0'&&root->data[0]<='9') return atof(root->data);else{switch(root->data[0]){case '+': return CalculateEepress(root->lChild)+CalculateEepress(root->rChild);case '-': return CalculateEepress(root->lChild)-CalculateEepress(root->rChild);case '*': return CalculateEepress(root->lChild)*CalculateEepress(root->rChild);case '/': return CalculateEepress(root->lChild)/CalculateEepress(root->rChild);}}}voidconstructExpress(node *&root){char sub[20];scanf("%s",sub);if(sub[0]>='0'&&sub[0]<='9') //此即为终止条件{root=(node *)malloc(sizeof(node));strcpy(root->data,sub);}else{root=(node *)malloc(sizeof(node));strcpy(root->data,sub);constructExpress(root->lChild);constructExpress(root->rChild);}}doubleCalculateEepressByString(){char sub[20];scanf("%s",sub);if(sub[0]>='0'&&sub[0]<='9'){returnatof(sub);}else{switch(sub[0]){case '+': return CalculateEepressByString()+CalculateEepressByString();case '-': return CalculateEepressByString()-CalculateEepressByString();case '*': return CalculateEepressByString()*CalculateEepressByString();case '/': return CalculateEepressByString()/CalculateEepressByString();}}}voidConvertEepressByString(){char sub[20];scanf("%s",sub);if(sub[0]>='0'&&sub[0]<='9'){printf("%s",sub);}else{switch(sub[0]){case '+': {ConvertEepressByString(); printf("%c",'+'); ConvertEepressByString();break;}case '-': {ConvertEepressByString(); printf("%c",'-'); ConvertEepressByString();break;}case '*': {ConvertEepressByString(); printf("%c",'*'); ConvertEepressByString();break;}case '/': {ConvertEepressByString(); printf("%c",'/'); ConvertEepressByString();break;}}}}// case后的break没有将如何?void main( ){node *exp;printf("请输入逆波兰式: \n");ConvertEepressByString();printf("\n");// constructExpress(exp);// printf("逆波兰式的结果为%f.\n",CalculateEepressByString());printf("Call CalculateEepress(node *root) %d次.\n",k);}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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;
}。

相关文档
最新文档