前言
最近在重新学习数据结构,看到栈的时候遇到了逆波兰表达式,特此记录一下。
逆波兰表达式介绍
表达式一般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,这称为中缀表达式(Infix Expression),如A+B。
波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式:
把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;前后缀表达式的出现是为了方便计算机处理,它的运算符是按照一定的顺序出现,所以求值过程中并不需要使用括号来指定运算顺序,也不需要考虑运算符号(比如加减乘除)的优先级。
逆波兰表达式的例子
中缀表达式 | 逆波兰表达式 |
---|---|
1 + 2 | 1,2,+ |
1 + 2 * 4 / 7 * 2 | 1,2,4,,7,/,2,,+ |
8 = 3 + 5 | 8,3,5,+,= |
17 - (8 + 9) | 17,8,9,+,- |
以上例子是怎么做到的呢
先来看第二个例子的中缀表达式:
1 + 2 * 4 / 7 * 2
第一步:所有算术表达式加上表明优先级的括号
(1 + (((2 * 4)/ 7)* 2))
第二步:将所有运算符移动到其相关表达式最内层的右括号外面
(1 (((2 4 )* 7)/ 2)* )+
第三步:去掉括号
1 2 4 * 7 / 2 * +
便得到了逆波兰表达式
来做道题吧
给定一个逆波兰表达式,求表达式的值。
解题思路:遇到数字就压栈,遇到运算符号就弹出栈顶的两个元素进行计算,将计算结果再次压回栈顶,重复以上,直到栈中只剩下一个元素,那就是计算结果。
核心代码如下:
import java.util.*;
public class Solution {
/**
* @param tokens string字符串一维数组
* @return int整型
*/
public int evalRPN (String[] tokens) {
// write code here
Stack<Integer> stack = new Stack<Integer>();
for(String token : tokens) {
if(isDigit(token)) {
stack.push(Integer.parseInt(token));
} else {
if(token.equals("+")) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 + num2);
} else if(token.equals("-")) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 - num2);
} else if(token.equals("*")) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 * num2);
} else if(token.equals("/")) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 / num2);
}
}
}
return stack.pop();
}
/* 判断字符串s能否转为整型 */
private boolean isDigit(String s) {
try {
Integer.parseInt(s);
return true;
} catch(Exception e) {
return false;
}
}
}