问题描述
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。
输入格式
输入一行,包含一个表达式。
输出格式
输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
思路
简单中缀表达式计算:
-
创建一个运算符栈和操作数栈
-
从左到右扫描表达式:
-
扫描到数字直接入操作数栈
-
扫描到运算符:
-
如果比运算符栈顶的符号优先级高,则直接入栈
-
如果比运算符栈顶的符号优先级低,则弹出栈顶符号和操作数栈中的两个数进行运算,结果再入栈
-
扫描到左括号直接入栈
-
扫描到右括号则循环弹出栈顶符号和操作数栈中的两个数进行运算,结果入栈,直到栈顶符号为左括号为止
-
如果表达式扫描完毕运算符栈还有元素,则继续出栈计算直到运算符栈为空
-
最后操作数栈的栈顶元素即为表达式的运算结果
代码
import java.util.Scanner;
import java.util.Stack;
public class Calculate {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String expression = input.nextLine();
input.close();
System.out.println(stack(expression));
}
public static Integer stack(String expression) {
Stack<Integer> operand = new Stack<>(); //操作数栈
Stack<String> operator = new Stack<>();//操作符栈
StringBuilder exp = new StringBuilder(expression);//将表达式保存为可变字符串
for (int i = 0; i < exp.length(); i++) {
if(exp.charAt(i) == '+' || exp.charAt(i) == '-' ||
exp.charAt(i) == '*' || exp.charAt(i) == '/') {
if(operator.empty()) {
operator.push(String.valueOf(exp.charAt(i)));
}
else if(priority(String.valueOf(exp.charAt(i))) > priority(operator.peek())) {
operator.push(String.valueOf(exp.charAt(i)));
}
else {//运算符优先级低,弹出栈顶元素进行运算
Integer obj1 = operand.pop();
Integer obj2 = operand.pop();
Integer res = result(obj2, obj1, operator.pop());
operand.push(res);
operator.push(String.valueOf(exp.charAt(i)));
}
}
else if(exp.charAt(i) == '(') {
operator.push(String.valueOf(exp.charAt(i)));
}
else if(expression.charAt(i) == ')') {//扫描到右括号则循环弹出栈顶符号和操作数栈中的两个数进行运算,结果入栈,知道栈顶符号为左括号为止
while(!operator.peek().equals("(")) {
Integer obj1 = operand.pop();
Integer obj2 = operand.pop();
Integer res = result(obj2, obj1, operator.pop());
operand.push(res);
}
operator.pop();
}
else if(exp.charAt(i) >= '0' && exp.charAt(i) <= '9'){ //扫描到数字直接入操作数栈
int j = i + 1;
StringBuilder num = new StringBuilder(String.valueOf(exp.charAt(i))); //处理多位数的情况
while(exp.charAt(j) >= '0' && exp.charAt(j) <= '9') {
num.append(exp.charAt(j));
exp.setCharAt(j, ' ');//将拼接过的数字置为空,以免重复入栈
j++;
}
operand.push(Integer.valueOf(num.toString()));
}
else {
continue;
}
}
if(!operator.empty()) { //表达式扫描完运算符栈还未空继续计算
while(!operator.empty()) {
Integer obj1 = operand.pop();
Integer obj2 = operand.pop();
Integer res = result(obj2, obj1, operator.pop());
operand.push(res);
}
}
return operand.peek();
}
public static int priority(String operator) { //运算符的优先级,数字越大,优先级越大
if(operator.equals("+") || operator.equals("-"))
return 1;
else if(operator.equals("*") || operator.equals("/"))
return 2;
else
return 0;
}
public static Integer result(int obj1, int obj2, String operator) {
Integer res = 0;
switch(operator) {
case "+": res = obj1 + obj2;break;
case "-": res = obj1 - obj2;break;
case "*": res = obj1 * obj2;break;
case "/": res = obj1 / obj2;
}
return res;
}
}