前缀、中缀、后缀表达式(逆波兰表达式)
1. 前缀表达式
1.1 概述
- 前缀表达式又称为波兰表达式,前缀表达式的运算符位于操作数之前
- 举例:(3+4)x5-6 的前缀表达式为- x + 3 4 5 6
1.2 前缀表达式计算机求值
从右至左扫描表达式,遇到数字时将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,使用运算符对他们做相应运算,并将结果入栈;重复上述过程直到表达式的最左端,最后运算得出的值即为表达式的结果。
例如:(3+4)x5-6对应的前缀表达式为- x + 3 4 5 6,针对前缀表达式的求值步骤如下:
- 从右向左扫描,将6 5 4 3压入堆栈
- 遇到+运算符,因此弹出两个元素3和4,并且对这两个元素做加法运算得到结果7,将7入栈
- 接下来遇到x运算,因此弹出7和5,计算出7x5结果为35,将35压入堆栈
- 最后遇到-运算,弹出两个元素,计算出35-6的值为29,因此最后的结果为29
2. 中缀表达式
- 中缀表达式就是常见的运算表达式,(3+4)x5-6
- 人最熟悉中缀表达式计算,但对计算机并不好操作,我们往往将中缀表达式转换为其他表达式来操作(一般为后缀表达式)
3. 后缀表达式
3.1 概述
- 后缀表达式又称为逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后
- 举例:(3+4)x5-6对应的后缀表达式就是3 4 + 5 x 6 -
正常表达式 | 逆波兰表达式 |
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 + = |
3.2 计算机求值
从左至右扫描表达式,遇到数字时将数字直接入栈,遇到运算符时弹出栈顶的两个数,用运算符对他们做相应运算,将结果入栈:重复上述过程知道表达式的最右端最后运算得出的值即为表达式的结果。
例如:(3+4)x5-6对应的后缀表达式为3 4 + 5 x 6 -,针对后缀表达式的求值步骤如下:
- 从左向右扫描,将3和4压入堆栈
- 遇到+运算符,因此弹出4和3,计算3+4的值为7,将7入栈
- 继续扫描,将5入栈
- 接下来遇到x运算符,因此弹出5和7,计算7x5的结果为35压入堆栈
- 将6入栈
- 最后为-运算,弹出6和35,计算35-6的值为29,即为表达式的值
七、逆波兰计算器
1. 分析
- 输入一个逆波兰表达式,使用栈计算其结果
- 支持小括号和多位数整数
2. 代码演示
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @author DELL
* @Date 2020/1/29 12:53
**/
public class PolandNotation {
public static void main(String[] args) {
String exception="30 4 + 5 x 6 -";
List<String> list = getListString(exception);
int res = calculator(list);
System.out.println("计算结果为:"+res);
}
/**
* 将表达式通过空格进行分割,将分割后的字符串存入list集合中,并返回list
* @param exception
* @return
*/
public static List<String> getListString(String exception){
//将exception进行分割
String[] s = exception.split(" ");
ArrayList<String> list = new ArrayList<>();
//将分割后的字符串放入list中
for (String s1 : s) {
list.add(s1);
}
return list;
}
public static int calculator(List<String> list){
Stack<String> stack = new Stack<>();
for (String s : list) {
//正则表达式取出数字
//匹配多位数
if(s.matches("\\d+")){
stack.push(s);
}else{
int num2=Integer.parseInt(stack.pop());
int num1=Integer.parseInt(stack.pop());
int res=0;
switch (s){
case "+":
res=num1+num2;
break;
case "-":
res=num1-num2;
break;
case "x":
res=num1*num2;
break;
case "/":
res=num1/num2;
break;
default:
throw new RuntimeException("运算符有误!");
}
stack.push(""+res);
}
}
return Integer.parseInt(stack.pop());
}
}