思路

中缀表达式适合人类阅读和计算,但是对于计算机来说,后缀表达式更合适。先把中缀表达式转换为后缀表达式,然后就可以轻松计算出后缀表达式的结果。

代码

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.util.ArrayList;
  5. import java.util.Deque;
  6. import java.util.LinkedList;
  7. import java.util.List;
  8. public class Main {
  9. public static void main(String[] args) throws IOException {
  10. BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
  11. String expression = reader.readLine().trim();
  12. List<String> infixList = infixToList(expression);
  13. System.out.println(infixList);
  14. List<String> postfixList = infixToPostfix(infixList);
  15. System.out.println(postfixList);
  16. int ans = calculate(postfixList);
  17. System.out.println(ans);
  18. }
  19. /**
  20. * 将中缀表达式的符号, 数字以List的形式存储
  21. *
  22. * @param expression 中缀表达式
  23. * @return List
  24. */
  25. private static List<String> infixToList(String expression) {
  26. List<String> ans = new LinkedList<String>();
  27. char[] chars = expression.toCharArray();
  28. for (int begin = 0, i = 0; i < chars.length; ) {
  29. // 符号
  30. if ((chars[i] < '0') || (chars[i] > '9')) {
  31. ans.add(chars[i] + "");
  32. ++i;
  33. begin = i;
  34. } else { // 整字
  35. while ((i < chars.length) && (chars[i] >= '0') && (chars[i] <= '9')) {
  36. ++i;
  37. }
  38. ans.add(expression.substring(begin, i));
  39. begin = i;
  40. }
  41. }
  42. return ans;
  43. }
  44. /**
  45. * 中缀表达式数组转后缀表达式数组
  46. *
  47. * @param infixList 中缀表达式数组
  48. * @return 后缀表达式数组
  49. */
  50. private static List<String> infixToPostfix(List<String> infixList) {
  51. List<String> ans = new ArrayList<>(infixList.size());
  52. // 符号栈
  53. Deque<String> stack = new LinkedList<>();
  54. for (String e : infixList) {
  55. if (e.equals("(")) { // 左括号直接入栈
  56. stack.push(e);
  57. } else if (e.equals(")")) { // 右括号入栈时, 一直出栈直到遇到将知道一个左括号
  58. while (!stack.peek().equals("(")) {
  59. // 栈顶元素出栈入队
  60. ans.add(stack.pop());
  61. }
  62. // 左括号直接出栈
  63. stack.pop();
  64. } else if (isOperator(e)) { // 遇到操作符
  65. // 栈为空或者栈顶元素优先级低则入栈
  66. if (stack.isEmpty() || (getPriority(stack.peek()) < getPriority(e))) {
  67. stack.push(e);
  68. } else {
  69. // 栈不为空且栈顶元素不为左括号且栈顶元素优先级大于党员元素, 则持续出栈入队
  70. while ((!stack.isEmpty()) && (!stack.peek().equals("("))
  71. && (getPriority(stack.peek()) >= getPriority(e))) {
  72. ans.add(stack.pop());
  73. }
  74. stack.push(e);
  75. }
  76. } else { // 遇到数字, 直接入队
  77. ans.add(e);
  78. }
  79. }
  80. while (!stack.isEmpty()) {
  81. ans.add(stack.pop());
  82. }
  83. return ans;
  84. }
  85. /**
  86. * 判断s是否为操作符
  87. *
  88. * @param s 输入字符串
  89. * @return s是操作符返回true, 否则返回false
  90. */
  91. private static boolean isOperator(String s) {
  92. return s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/");
  93. }
  94. /**
  95. * 栈中元素优先级
  96. *
  97. * @param s 字符串
  98. * @return 该符号优先级
  99. */
  100. private static int getPriority(String s) {
  101. switch (s) {
  102. case "+":
  103. case "-":
  104. return 1;
  105. case "*":
  106. case "/":
  107. return 2;
  108. }
  109. // 左括号优先级最低
  110. return -1;
  111. }
  112. /**
  113. * 后缀表达式求值
  114. *
  115. * @param list 后缀表达式数组
  116. * @return 计算结果
  117. */
  118. private static int calculate(List<String> list) {
  119. // 结果栈
  120. Deque<Integer> stack = new LinkedList<>();
  121. int num1, num2;
  122. for (String e : list) {
  123. if (isOperator(e)) {
  124. num2 = stack.pop();
  125. num1 = stack.pop();
  126. switch (e) {
  127. case "+":
  128. stack.push(num1 + num2);
  129. break;
  130. case "-":
  131. stack.push(num1 - num2);
  132. break;
  133. case "*":
  134. stack.push(num1 * num2);
  135. break;
  136. case "/":
  137. stack.push(num1 / num2);
  138. break;
  139. }
  140. } else {
  141. stack.push(Integer.parseInt(e));
  142. }
  143. }
  144. return stack.pop();
  145. }
  146. }

参考

https://www.cnblogs.com/menglong1108/p/11619896.html