题解 | #四则运算#
四则运算
https://www.nowcoder.com/practice/9999764a61484d819056f807d2a91f1e
import java.util.Scanner;
import java.util.Stack;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
int length = s.length();
// 存储临时得到的数字
int num = 0;
// 数字的符号
int sign = 1;
// 存储是否有数字
boolean hasNum = false;
// 后缀表达式,用集合存储
List<Object> postfix = new ArrayList<>();
// 存储运算符的栈
Stack<Character> stack1 = new Stack<>();
// 1. 遍历中缀表达式,得到后缀表达式
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
// 如果是数字,更新数字大小
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
hasNum = true;
} else { // 不是数字
// 如果有,将之前的num放进去
if (hasNum) {
postfix.add(num * sign);
// 重置数字相关标记
sign = 1;
num = 0;
hasNum = false;
}
// 负号,特点:在第一个位置,或者前面有左括号
if (c == '-' && (i == 0 || isLeftBracket(s.charAt(i - 1)))) {
sign = -1;
} else if (isRightBracket(c)) { // 右括号
// 直到碰到左括号之前
while (!isLeftBracket(stack1.peek())) {
// 弹出运算符号,加入后缀表达式
postfix.add(stack1.pop());
}
// 弹出并消除左括号,不能加入后缀表达式
stack1.pop();
} else { // 其它操作符号,包括左括号
// 如果c不优先,将栈顶符号弹出来送后缀表达式
while (!stack1.isEmpty() && !prior(c, stack1.peek())) {
postfix.add(stack1.pop());
}
// c优先(或空栈),压栈
stack1.push(c);
}
}
}
// 如果还有数字,添加进去
if (hasNum) {
postfix.add(num * sign);
}
// 弹出剩下的运算符
while (!stack1.isEmpty()) {
postfix.add(stack1.pop());
}
// 测试
// System.out.print("后缀表达式:");
// for (Object o : postfix) {
// System.out.print(" " + o);
// }
// System.out.println();
// 2. 计算后缀表达式
// 存储操作数的栈
Stack<Integer> stack2 = new Stack<>();
// 遍历后缀表达式
for (Object o : postfix) {
// 是数字
if (o.getClass() == Integer.class) {
// 压栈
stack2.push((Integer)o);
} else {
// 是运算符
// 弹出两个数字
int num1 = stack2.pop();
int num2 = stack2.pop();
// 计算运算结果
int result = calculate(num2, num1, (char)o);
// 结果压栈
stack2.push(result);
}
}
// 最后的栈顶元素即为结果
System.out.println(stack2.pop());
}
// 是否为运算符
public static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/';
}
// 是否为左括号
public static boolean isLeftBracket(char c) {
return c == '(' || c == '[' || c == '{';
}
// 是否为右括号
public static boolean isRightBracket(char c) {
return c == ')' || c == ']' || c == '}';
}
// 是否c1比c2更优先
public static boolean prior(char c1, char c2) {
// 左括号进来前优先级最高,进来后优先级最低
if (isLeftBracket(c1) || isLeftBracket(c2)) {
return true;
}
// 乘除比加减优先
if ((c1 == '*' || c1 == '/') && (c2 == '+' || c2 == '-')) {
return true;
}
return false;
}
// 根据操作符号计算结果并返回
public static int calculate(int a, int b, char c) {
if (c == '+') {
return a + b;
} else if (c == '-') {
return a - b;
} else if (c == '*') {
return a * b;
} else {
return a / b;
}
}
}
