题解 | #表达式求值#
表达式求值
https://www.nowcoder.com/practice/9566499a2e1546c0a257e885dfdbf30d
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.Scanner;
public class Main {
static Map<Character, Integer> map = new HashMap<>();
static{//为运算符映射优先级,后面判断运算符压栈时需要用到
map.put('(', -1);
map.put('+', 0);
map.put('-', 0);
map.put('*', 1);
map.put('/', 1);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char[] exp = in.next().toCharArray();
in.close();
//char[] exp = "(7+5*4*3+6)".toCharArray();
Stack<Character> opeStack = new Stack<>();
Stack<Integer> numStack = new Stack<>();
boolean continueNum = false;//用来辅助判断是否存在连续的数字字符,每当迭代到数字字符则置真,迭代到非数字字符则置假
boolean negativeNum = false;//为真则表示本次数字要乘以-1,假则不用乘
char preChar = '@';//表示上一个字符,用来辅助判断‘-’是减号还是负号,处在字符串开头或者左括号右边的‘-’,都应是负号
for(char c: exp){
//如果字符为操作数,则压入操作数栈
if(Character.isDigit(c)){
if(!continueNum){//如果上一个字符为非数字字符则压栈
if(negativeNum){//如果上一个字符是‘-’,且判断出来是负号,而不是减号,则数字应是负数
numStack.push(-1 * (c - '0'));
negativeNum = false;
}else {//正数压栈
numStack.push(c - '0');
}
continueNum = true;//置为真,如果下一个字符还是数字的话,根据这个布尔值可以正确处理连续的数字字符
}else{//如果上一个字符是数字字符,则把上一个压栈数字弹出乘以十再加上当前数字再压栈
numStack.push(numStack.pop() * 10 + (c - '0'));
}
} else {
continueNum = false;
//如果之前的字符是@或者(,且当前的字符为‘-’,则当前‘-’字符不是运算符,是负号
if((preChar == '@' || preChar =='(') && c == '-'){
negativeNum = true;
}else if(opeStack.isEmpty() && c != '-' || c == '('){//如果运算符栈顶为空或者是左括号,则直接把新运算符压入运算符栈
opeStack.push(c);
}else if(c == ')'){//如果是右括号,则一直执行计算,直到遇到左括号为止
while(opeStack.peek() != '('){
cal(opeStack, numStack);
}
//弹出左括号
opeStack.pop();
}else {
//运算符栈不为空且当前字符不是‘-’,判断两运算符优先级
while(true){//如果旧运算符比新运算符优先级更高,则不断弹出旧运算符并执行,直到新运算符优先级更高或者运算符栈为空为止
if(opeStack.isEmpty()) break;
char oldOpe = opeStack.peek();
//如果旧运算符等级大于等于新运算符等级,则先执行旧运算符的运算,否则不执行计算
if(map.get(oldOpe) >= map.get(c)) {
cal(opeStack, numStack);
}else{
break;
}
}
//再把新操作符压入运算符栈
opeStack.push(c);
}
}
preChar = c;
}
//迭代完字符串后,可能只把最后一个数字压栈,就没有继续操作运算符栈里的操作符了,所以这里要做最后的计算
while(!opeStack.isEmpty()){
cal(opeStack, numStack);
}
System.out.println(numStack.pop());
}
/**
* 弹出操作数栈两个数,弹出运算符栈一个运算符,执行计算并把最终计算的值压栈
* @param opeStack 运算符栈
* @param numStack 操作数栈
*/
static void cal(Stack<Character> opeStack, Stack<Integer> numStack){
char ope = opeStack.pop();
int y = numStack.pop();
int x = numStack.pop();
int z = 0;
if(ope == '+'){
z = x + y;
}else if(ope == '-'){
z = x - y;
}else if(ope == '*'){
z = x * y;
}else if(ope == '/'){
z = x / y;
}
numStack.push(z);
}
}
