栈的应用----四则运算,后缀逆波兰表示法(RPN)

我们从小就学习四则运算——加减乘除四则。我们也知道,要先乘除后加减,遇到括号要先算括号内的。可是,想让计算机进行这样的四则运算可不容易,它可不知道什么乘除优先,然后加减。那么,该如何让计算机也能进行这样的四则运算呢?就是通过栈。

我们人类非常熟悉也非常喜欢用中缀表示法进行算数运算,什么是中缀表示法呢?也就是,一个运算符在两个数字中间。比如,5+3,3*5,5/2等等,这些都是中缀表示法。这种表示法很适合人类使用,但是却不适用于计算机,于是,我们就想出了一种适合计算机的表示方式,叫做,后缀表示法,也就是运算符出现在待运算数字的后面。比如,5+3,这种叫做中缀表示法,用后缀表示法就是,5 3 +,这样的方式就是后缀表示法。也就是说,想让计算机进行运算,首先就要把中缀表达式转换成后缀表达式。接着才是对后缀表达式进行运算。

那么先来讲,中缀表达式转换成后缀表达式是如何通过栈实现的。我们假设有这么一个中缀表达式:

5 + 4 * 6 / ( 3 + 7 ) * 2 + 1

我们遵循这样的一个原则,遇到数字就直接将数字输出,遇到运算符就将运算符压入栈中。如果当前运算符跟栈顶运算符相比,优先级高于栈顶运算符,就将此运算符压入栈中,该运算符成为新的栈顶运算符。换言之,如果该运算符不高于栈顶运算符,则栈顶元素依次出栈,并将当前符号进栈。好了,开始转换。首先是5,所以,我们要将5输出,因为5是数字,遇到数字就直接输出,那么输出为:

5

接着是一个“+”,因为是运算符,所以将运算符入栈。

+

接着,仍然是数字,所以将4输出,

5 4

由于接下来的是一个乘号,所以,要将它与栈顶的运算符进行对比,发现*号优先级高于+号优先级,所以,将*号入栈,这样以来,栈顶元素就为*号。

+ *

由于6也是数字,所以,可以将其输出

5 4 6

接下来,是个关键。因为,接下来的一个符号是/号,所以,当它和*号对比时,发现/号优先级并不高于*号优先级,所以,将栈顶元素依次出栈,也就是

*

所以,目前,输出元素为

5 4 6 *

然后,将/号入栈,此时栈中只有一个符号/

+ /

接着,是一个左括号( ,所以要将(入栈,直到碰到)是将括号内的内容出栈。

+ / (

因为是数字,所以将3出栈

5 4 6 * 3

接着将+号入栈

+ / ( +

接着是一个数字7,很明显,将数字7出栈

5 4 6 * 3 7

这时碰到了),所以要将+出栈,

5 4 6 * 3 7 +

此时,栈中元素为,

+ /

接着是一个*号,将它与/号对比,发现,它不高于*号,所以,将/出栈,然后跟+号对比,发现高于+号,所以,*可以入栈了,所以,输出元素如下:

5 4 6 * 3 7 + /

栈中数据如下:

+ *

接着是一个数字2,将2直接输出

5 4 6 * 3 7 + / 2

接着是一个+号,优先级并不高于*号,也不高于栈底的+号,所以,将栈顶元素依次出栈,

5 4 6 * 3 7 + / 2 * +

然后将该+号入栈,所以,此时栈内元素为

+

当碰到最后一个1的时候,直接将1输出。

5 4 6 * 3 7 + / 2 * + 1

最后了,已经没有元素了,此时,就将栈中的+号输出,所以,最后,后缀表达式为:

5 4 6 * 3 7 + / 2 * + 1 +

此时,已经将我们人类认识的中缀表达式转换成了机器认识的后缀表达式。那么,此时,就可以开始运算了,运算还是需要借助栈。当碰到数字时,还是需要将数字压入栈,当碰到运算符时,从栈顶将元素取出,并进行运算。比如,5 4 6都是数字,于是,将5 4 6入栈,

5 4 6

接下来碰到了*号,所以,将6取出作为乘数,将4取出作为被乘数,进行相乘运算,4 * 6 = 24,此时,将运算结果24存入栈中。所以,栈中元素为:

5 24

因为3 7都是数字,所以,将3 7保存至栈中。

5 24 3 7

因为接下来碰到了一个+号,所以,将7和3取出,进行3 + 7 = 10的运算,然后将运算结果10放入栈中。

5 24 10

接下来是一个/号,所以,将10取出作为除数,将24取出作为被除数,所以,24 / 10 = 2.4,然后将2.4存入栈中,所以,

5 2.4

接下来,是一个数字2,所以,将2压入栈中

5 2.4 2

然后是一个乘号,所以将2和2.4取出,执行2.4 * 2 = 4.8,将4.8压入栈中

5 4.8

因为接下来是一个+号,所以将5和4.8取出,执行5 + 4.8 = 9.8,此时将9.8入栈

9.8

然后将数字1入栈

9.8 1

最后一个+号,所以将两个数出栈,执行9.8 + 1 = 10.8,最后运算结果为,10.8。到此就完全结束了。

其实,我举的这个例子是有问题的,栈中保存的是类型相同的元素,所以我这个例子举的不好,不过不影响总结计算机执行四则运算的过程。

时间: 2024-10-08 00:33:17

栈的应用----四则运算,后缀逆波兰表示法(RPN)的相关文章

leetcode-计算逆波兰表示法的值

package edu.bupt.cici.leetcode; import java.util.ArrayList; public class EvaluateReversePolishNotation { public int evalRPN(String[] tokens) { int temp = 0; int length = tokens.length; ArrayList<Integer> stack = new ArrayList<Integer>(); for (

逆波兰表示法

逆波兰表示发是一种将运算符写在操作数后面的描述程序(算式)的方法.举个例子,我们平常用中缀表示法描述的算式(1 + 2) * (5 + 4),改为逆波兰表示法之后则是1 2 + 5 4 + *.相较于中缀表示法,逆波兰表示法的优势在于不需要括号. 请输出以逆波兰表示法输入的算式的计算结果. 输入   在1行中输入1个算式.相邻的符号(操作数或运算符)用1个空格隔开. 输出   在1行之中输出计算结果. 限制   2≤算式中操作数的总数≤100 1≤算式中运算符的总数≤99 运算符仅包括"+&qu

leetcode栈--1、evaluate-reverse-polish-notation(逆波兰表达式)

题目描述 Evaluate the value of an arithmetic expression inReverse Polish Notation. Valid operators are+,-,*,/. Each operand may be an integer or another expression. Some examples: ["2", "1", "+", "3", "*"] -&g

栈的应用之求逆波兰表达式的值

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<ctype.h> 4 5 #define OK 1 6 #define ERROR 0 7 #define STACK_INIT_SIZE 20 8 #define STACK_INCREMENT 10 9 #define DIGITBUFFER 10 10 11 typedef int Status; 12 typedef double Elemtype; 13 t

逆波兰表达式(RPN)算法简单实现

算法分析: 一.预处理 给定任意四则运算的字符串表达式(中缀表达式),preDeal预先转化为对应的字符串数组,其目的在于将操作数和运算符分离. 例如给定四则运算内的中缀表达式: String infix = "100+8*5-(10/2)*5+10.5"; 字符串数组化后得: {"100","+","8","*","5","-","(",&quo

[从今天开始修炼数据结构]栈、斐波那契数列、逆波兰四则运算的实现

一.栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表.允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom).栈又称后进先出的线性表,简称LIFO结构. 注意:首先它是一个线性表,也就是说栈元素有前驱后继关系. 栈的插入操作,叫做进栈,也称压栈.入栈 栈的删除操作,叫做出栈,也叫弹栈. 注意:最先入栈,不代表就要最后出栈.因为栈没有限制出栈的时间,例如可以先入栈两个元素,再出栈两个元素,后入栈其他元素. 二.栈的抽象数据类型 ADT Stack Data 同线性表.元素具有相

逆波兰式篇(后缀表达式)

一.逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面.也称为后缀表达式. 二.一般算法 将一个普通的中序表达式转换为逆波兰表达式的一般算法是: 首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则. 读入一个中缀表达式,为了方便起见,可在其最右端追加一个最低优先级运算符(如:#号).(这样做的目的是,最后读入#号运算符时将运算符栈中所有运算符都输       出). 从左至右扫描该中

逆波兰表达式(栈,递归)

1696:逆波兰表达式 总时间限制:  1000ms 内存限制:  65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4.本题求解逆波兰表达式的值,其中运算符包括+ - * /四个. 输入 输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数. 输出 输出为一行,表达式的值.可直接用pr

leetcode 150. 逆波兰表达式求值(栈)

根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的.换句话说,表达式总会得出有效数值且不存在除数为 0 的情况. 示例 1: 输入: ["2", "1", "+", "3", "*"] 输出: 9 解释: ((2 + 1) * 3) = 9 示例 2: 输入: [&qu