后缀表达式求值是非常典型的题目,这类题型一般使用二叉树的后序遍历来求解,本题使用栈的求解方式来解决
例题:150.逆波兰表达式求值
代码 :
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<Integer>();
/*使用deque接口来实现栈,Java中栈接口stack本身的语意不不能很好的表述栈的数据结构,使用deque来实现栈更高效和准确,有两种实现方式:
使用LinkedList作为栈效率高(底层用链表来实现)。
使用ArrayDeque作为队列效率高(底层使用数组来实现)。
*/
int n = tokens.length;
for (int i = 0; i < n; i++) {
String token = tokens[i];
if (isNumber(token)) {
stack.push(Integer.parseInt(token));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
switch (token) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
default:
}
}
}
return stack.pop();
}
public boolean isNumber(String token) {
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}
}
总结点:首先说明一下本题的解题逻辑还是比较简单的:遍历字符串数组,遇到运算数则压栈,遇到运算符则将栈中前两个运算数弹栈做相应的运算然后再压栈,反复如此知道最后弹出结果。
1.后缀表达式
所谓后缀表达式就是中缀表达式(我们平常看到的计算式)的后缀形式即运算符在对应的运算数后面,这种形式能够让计算机更好地理解。例如:4 + 13 / 5,这就是中缀表达式,计算机从左到右去扫描的话,扫到13,还要判断13后面是什么运算符号,还要比较一下优先级,然后13还和后面的5做运算,做完运算之后,还要向前回退到 4 的位置,继续做加法,这样是非常麻烦的,那么将中缀表达式,转化为后缀表达式之后:["4", "13", "5", "/", "+"] ,就不一样了,计算机可以利用栈里顺序处理,不需要考虑优先级了。
2.栈的实现
(1)Java中栈的实现一般不用stack而用deque接口来实现具体原因如下:Java是继承自vector的,因为Vector是当初JAVA曾经写得不太行的类,所以Stack也不太行。Vector不行是因为效率不太行,很多方法都用了synchronized修饰,虽然线程安全,但是像ArrayDeque,LinkedList这些线程不安全的,在需要安全的时候也可以用Collections.synchronizedCollection()转化成线程安全的,所以Vector就没什么用处了。再根据仿生学Stack只能上进上出,有点像刺胞动物(腔肠动物),就是那种从哪里吃进去就哪里拉出来的那种生活在海洋里的比较低级的生物。Deque上进上出,上进下出,甚至下进上出,非常上流,只有你想不到,没有我Deque做不到的。
(2)栈的实现有两种方法:
Deque<Integer> stack = new ArrayDeque<>();
Deque<Integer> stack = new LinkedList<>();