Java解析字符串表达式--逆波兰表达式的计算

问题来由:

读入一个字符串形式的四则运算表达式,输出对应的计算结果。如读入的是“6 * ( 5 + ( 2 + 3) * 8 + 3)”,那么解析后的输出结果应为288。

思路:

  1. 一般的计算过程是这样的,首先计算优先级最高的小括号里面的内容,即“( 5 + ( 2 + 3) * 8 + 3)”,
  2. 将“2 + 3”的计算结果并存为A,接着用计算“A*8”,并存为B
  3. 计算“5+B+3”,结果存为C
  4. 最后计算“6*C”,计算完毕

我们可以将这种操作顺序书写如下:

6 5 2 3 + 8 * + 3 + *

这个记法就是逆波兰(reverse Polish)表达式,其求值过程恰好就是上面所描述的过程。逆波兰表达式又叫做后缀(postfix)表达式。在通常的表达式中,运算符总是置于与之相关的两个运算对象之间,所以,这种表示法也称为中缀表示。波兰逻辑学家 J.Lukasiewicz于1929年提出了另一种表示表达式的方法。按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。

后缀表达式的计算

计算后缀表达式最简单的方法就是使用一个栈:

  • 当读到一个数字时就将它压入栈中
  • 读到一个运算符时,就从栈中弹出两个数字,并将该运算符作用于这两个数字,然后将计算结果再压入栈中

下面演示下“6 5 2 3 + 8 * + 3 + *”的处理过程

  1. 首先读到 6 5 2 3 四个数字,没啥说的,直接打入栈中(6 5 2 3)
  2. 读到运算符“+”,从栈中弹出两个数字“3”、“2”,计算 3+2 = 5,将计算结果压入栈中;(6 5 5)
  3. 读到8,压入栈(6 5 5 8)
  4. 读到“*”,从栈中弹出两个数字“8”、“5”,计算 8 * 5 = 40,将计算结果压入栈中;(6 5 40)
  5. 读到“+”,从栈中弹出两个数字“40”、“5”,计算 40 + 5 = 45,将计算结果压入栈中;(6 45)
  6. 读到3,压入栈(6 45 3)
  7. 读到“+”,从栈中弹出两个数字“3”、“45”,计算 3 + 45 = 48,将计算结果压入栈中;(6 48)
  8. 读到“*”,从栈中弹出两个数字“48”、“6”,计算 48 * 6 = 288,计算完毕!!!

计算一个后缀表达式话费的时间是O(N),该算法的计算非常简单,同时不需要知道任何的计算优先级。

那么现在的问题就是如何将一个正常的表达式转换为后缀表达式???

且看下回分解。

时间: 2024-10-21 09:35:11

Java解析字符串表达式--逆波兰表达式的计算的相关文章

JavaScript实现计算后缀表达式(逆波兰表达式)以及将中缀表达式转为后缀表达式

逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出.逆波兰表达式又叫做后缀表达式.这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子: 正常的表达式 逆波兰表达式 a+b ---> a,b,+ a+(b-c) ---> a,b,c,-,+ a+(b-c)d ---> a,d,b,c,-,,+ a=1+3 ---> a=1,3 + http=(smtp+http+telnet)/1024 写成什么呢? http=smtp,http,telnet,+,+,1

Java解析字符串表达式--逆波兰表达式的生成

上回讲了如何计算后缀表达式,其实真正的难点在于如何将一个正常的字符串表达式(中缀表达式)变成一个后缀表达式.如将6 * ( 5 + ( 2 + 3) * 8 + 3)变为6 5 2 3 + 8 * + 3 + * 逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出.逆波兰表达式又叫做后缀表达式.这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子: 正常的中缀表示 逆波兰表达式 a+b a,b,+ a+(b-c) a,b,c,-,+ a+(b-c)*d a,b,c,-,

栈的典型实例问题——后缀表达式(逆波兰记号)的计算

//编译程序一般使用后缀表达式求解表达式的值(RPN或者逆波兰记号)//计算后缀表达式的过程为:扫描,如果该项是操作数,压栈:如果是操作符,则从栈中退出两个操作数(先退出的是右操作//数),进行运算,并将运算结果重新压入栈中,扫描完后栈顶存放的就是计算结果.//注意的地方:是否支持2位以上的操作数!//操作数之间也肯定是有分割符的: //比如:12 34 56 * + //如果是123456*+,不管是人还是计算机,都是没法做的: 1 #include<iostream> 2 #include

栈的应用之中缀表达式转化为后缀表达式(逆波兰表达式)

1 #include<stdio.h> 2 #include<stdlib.h> 3 4 #define OK 1 5 #define ERROR 0 6 #define STACK_INIT_SIZE 20 7 #define STACK_INCREMENT 10 8 9 typedef char Elemtype; 10 typedef int Status; 11 12 typedef struct StackNode{ 13 Elemtype* base; 14 Elemt

求解逆波兰表达式(前缀表达式)

首先介绍一下逆波兰表达式 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4. 这个表达式的求法有很多种 这里介绍一种用递归求解的方法.. 时间复杂度O(n); 首先我们需要把表达式转换成运算符和数字. 用一个数组记录i位置是数字还是运算符. 如果是数字是浮点数的话可使用atof(str)把字符串转换为一个doubl

北京大学 程序设计与算法(二)逆波兰表达式

用递归解决递归形式的问题 逆波兰表达式 逆波兰表达式是一种把运算符前置的算数表达式,例如普通的表达式2+3的逆波兰表示法为+2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2+3)*3的逆波兰表示法为*+234.本题求解逆波兰表达式的值,其中运算符包括+-*/四个. 输入 输入为一行,其中运算符和运算数之间都用空格分隔,运算符是浮点数 输出 输出为一行,表达式的值. *+11.0 12.0 +24.0 35.0 --à(11.0+12.0)*(24.0+3

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

逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出.逆波兰表达式又叫做后缀表达式.下面是一些例子: 正常的表达式 逆波兰表达式 a+b ---> a,b,+ a+(b-c) ---> a,b,c,-,+ a+(b-c)*d ---> a,b,c,-,d,*,+ a+d*(b-c)--->a,d,b,c,-,*,+ a=1+3 ---> a=1,3 + 通过后缀表达式计算表达式值的过程:顺序访问表达式的每一项,若该项为操作数,则将其压入栈中:若该项是操作符<o

简单计算机——逆波兰表达式

逆波兰数:逆波兰数由两部分组成(操作数,操作符)--是波兰表达式的一种,即操作符在操作数的后面. 形式:A+B*C-D = ABC*D-; (A+B)*C-D = AB+C*D-; 既然我们知道了,后缀表达式那我们表达式是唯一的吗?我们来看一组数据: 例如:(A+B)*C-D 和 C*(A+B)-D; 很显然第二个的表达式为:C*AB+D-;虽然对最后的结果无影响,但我们需要知道逆波兰的多样性. 注意事项: 1.如果出现1+23 = 123+,该如何判断它的数值呢? 可以利用分割符来进行很好的辅

递归--逆波兰表达式

用递归解决递归形式的问题例题:逆波兰表达式逆波兰表达式是一种把运算符前置的算术表达式(其实一般教科书上称这种表达式为波兰表达式) ,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4.本题求解逆波兰表达式的值,其中运算符包括+ - * /四个. 输入:输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数 输出:输出为一行,表达式的值. 简单来说,这种