思路
中缀表达式适合人类阅读和计算,但是对于计算机来说,后缀表达式更合适。先把中缀表达式转换为后缀表达式,然后就可以轻松计算出后缀表达式的结果。
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String expression = reader.readLine().trim();
List<String> infixList = infixToList(expression);
System.out.println(infixList);
List<String> postfixList = infixToPostfix(infixList);
System.out.println(postfixList);
int ans = calculate(postfixList);
System.out.println(ans);
}
/**
* 将中缀表达式的符号, 数字以List的形式存储
*
* @param expression 中缀表达式
* @return List
*/
private static List<String> infixToList(String expression) {
List<String> ans = new LinkedList<String>();
char[] chars = expression.toCharArray();
for (int begin = 0, i = 0; i < chars.length; ) {
// 符号
if ((chars[i] < '0') || (chars[i] > '9')) {
ans.add(chars[i] + "");
++i;
begin = i;
} else { // 整字
while ((i < chars.length) && (chars[i] >= '0') && (chars[i] <= '9')) {
++i;
}
ans.add(expression.substring(begin, i));
begin = i;
}
}
return ans;
}
/**
* 中缀表达式数组转后缀表达式数组
*
* @param infixList 中缀表达式数组
* @return 后缀表达式数组
*/
private static List<String> infixToPostfix(List<String> infixList) {
List<String> ans = new ArrayList<>(infixList.size());
// 符号栈
Deque<String> stack = new LinkedList<>();
for (String e : infixList) {
if (e.equals("(")) { // 左括号直接入栈
stack.push(e);
} else if (e.equals(")")) { // 右括号入栈时, 一直出栈直到遇到将知道一个左括号
while (!stack.peek().equals("(")) {
// 栈顶元素出栈入队
ans.add(stack.pop());
}
// 左括号直接出栈
stack.pop();
} else if (isOperator(e)) { // 遇到操作符
// 栈为空或者栈顶元素优先级低则入栈
if (stack.isEmpty() || (getPriority(stack.peek()) < getPriority(e))) {
stack.push(e);
} else {
// 栈不为空且栈顶元素不为左括号且栈顶元素优先级大于党员元素, 则持续出栈入队
while ((!stack.isEmpty()) && (!stack.peek().equals("("))
&& (getPriority(stack.peek()) >= getPriority(e))) {
ans.add(stack.pop());
}
stack.push(e);
}
} else { // 遇到数字, 直接入队
ans.add(e);
}
}
while (!stack.isEmpty()) {
ans.add(stack.pop());
}
return ans;
}
/**
* 判断s是否为操作符
*
* @param s 输入字符串
* @return s是操作符返回true, 否则返回false
*/
private static boolean isOperator(String s) {
return s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/");
}
/**
* 栈中元素优先级
*
* @param s 字符串
* @return 该符号优先级
*/
private static int getPriority(String s) {
switch (s) {
case "+":
case "-":
return 1;
case "*":
case "/":
return 2;
}
// 左括号优先级最低
return -1;
}
/**
* 后缀表达式求值
*
* @param list 后缀表达式数组
* @return 计算结果
*/
private static int calculate(List<String> list) {
// 结果栈
Deque<Integer> stack = new LinkedList<>();
int num1, num2;
for (String e : list) {
if (isOperator(e)) {
num2 = stack.pop();
num1 = stack.pop();
switch (e) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
}
} else {
stack.push(Integer.parseInt(e));
}
}
return stack.pop();
}
}