逆波兰计算器
设计一个逆波兰计算器,可以完成如下任务:
(1)输入一个逆波兰表达式(后缀表达式),使用栈(stack),计算其结果。
(2)支持小括号和多位数整数。
(3)思路分析
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 和 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
Demo:
例如: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 - , 针对后缀表达式求值步骤如下:
(1)从左至右扫描,将3和4压入堆栈;
(2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
(3)将5入栈;
(4)接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
(5)将6入栈;
(6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果
(4)代码实现
1 import java.util.ArrayList;
2 import java.util.List;
3 import java.util.Stack;
4
5 public class PolandNotation {
6
7 public static void main(String[] args) {
8 // 先定义一个逆波兰表达式
9 // (3+4)*5-6 => 3 4 + 5 *6 - = 29
10 // 为了方便,数字和符号使用空格间隔
11 String suffixExpression = "3 4 + 5 * 6 -";
12
13 // 思路
14 // 1.先将表达式放入 ArrayList 中
15 // 2.将 ArrayList 传递给一个方法,遍历 Arraylist,配合栈,完成计算
16
17 List<String> list = getListString(suffixExpression);
18 System.out.println("List=" + list);
19
20 int res = calculate(list);
21 System.out.println("计算的结果是=" + res);
22 }
23
24 // 将一个逆波兰表达式,依次将数据和运算符放入到 ArrayList中
25 public static List<String> getListString(String suffixExpression) {
26 // 将 表达式分割
27 String[] split = suffixExpression.split(" ");
28 List<String> list = new ArrayList<String>();
29 for (String ele : split) {
30 list.add(ele);
31 }
32 return list;
33 }
34
35 // 完成对逆波兰表达式的计算
36 /*
37 * 1)从左至右扫描,将3和4压入堆栈
38 * 2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
39 * 3)将5入栈;
40 * 4)接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
41 * 5)将6入栈;
42 * 6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果
43 */
44
45 public static int calculate(List<String> ls) {
46 // 创建一个栈,只需要一个栈
47 Stack<String> stack = new Stack<String>();
48 // 遍历 ls
49 for (String item : ls) {
50 // 使用正则表达式来取出数
51 if (item.matches("\d+")) { // 匹配的是多位数
52 // 入栈
53 stack.push(item);
54 } else {
55 // pop出两个数并运算,再入栈
56 int num2 = Integer.parseInt(stack.pop());
57 int num1 = Integer.parseInt(stack.pop());
58 int res = 0;
59 if (item.equals("+")) {
60 res = num2 + num1;
61 } else if (item.equals("-")) {
62 res = num1 - num2;
63 } else if (item.equals("*")) {
64 res = num2 * num1;
65 } else if (item.equals("/")) {
66 res = num1 / num2;
67 } else {
68 throw new RuntimeException("运算符有误");
69 }
70
71 // res 入栈
72 stack.push(res + "");
73 }
74 }
75 // 最后留在stack中的数据就是运算结果
76 return Integer.parseInt(stack.pop());
77 }
78
79 }