逆波兰表达式(Reverse Polish Notation)
1. 在算法中常说的后缀表达式,简单来说就是将正常的四则运算换一个写法
1+2 = 3 -> 12+ = 3
在习惯了这样的表达方式之后,我们将四则运算快速的转换成以下的表达方式,这里抄袭几个网上的例子:
["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
利用栈的方式来处理这样的后缀表达式是非常方便的,他的原理也变得很简单易懂:
- 从左至右依次读取
- 遇到符号取出前两位的数字(利用栈的特性,先进先出)
- 按照符号计算后,将结果再次压入栈内
举个例子: ["2", "1", "+", "3", "*"] 逐步分解:
- 模拟栈:从左至右读取放入栈,数据从栈顶输入即入口,从栈底被推出即出口。依次读入2,1两个数字放入栈
- 模拟栈:读取到符号【+】,不放入栈,连续从栈底取数,依次取出2位:2,1进行加法运算。得到的3再次压入栈内。到此为止,栈内只有3这一个数
- 模拟栈:继续读取列表,【+】号后面是数字3,放入栈内。目前栈内有两个3
- 模拟栈:继续读取列表,符号【*】,不放入栈,连续从栈底取数,依次取出2位:3,3进行乘法运算。得到的9再次压入栈内
- 模拟栈:继续读取列表,列表结束无结果,从栈底推出一位:9;此值即为答案
从这个例子来看,利用堆栈的特性能非常简单的用程序来完成这个四则运算。没有括号,不用作特殊判定,非常简便。但是还没有想好,怎么能非常方便的将中缀表达式转换成后缀表达式,或者这个思路本身就是错的?因该被运用在其他场景中。下面献上计算后缀表达式的代码:其实理解思路后,代码已经不那么重要了(代码也是转自网上的哈)public class Test { public static void main(String[] args) throws IOException { String[] tokens = new String[] { "2", "1", "+", "3", "*" }; System.out.println(evalRPN(tokens)); } public static int evalRPN(String[] tokens) { int returnValue = 0; String operators = "+-*/"; Stack<String> stack = new Stack<String>(); for (String t : tokens) { if (!operators.contains(t)) { stack.push(t); } else { int a = Integer.valueOf(stack.pop()); int b = Integer.valueOf(stack.pop()); switch (t) { case "+": stack.push(String.valueOf(a + b)); break; case "-": stack.push(String.valueOf(b - a)); break; case "*": stack.push(String.valueOf(a * b)); break; case "/": stack.push(String.valueOf(b / a)); break; } } } returnValue = Integer.valueOf(stack.pop()); return returnValue; } }