整体思路
该代码的目的是实现一个能够解析并计算包含数字、四则运算符(+、-、*、/)以及括号的字符串表达式的值的计算器功能,且不依赖 Java 的内置eval函数。核心思路是利用两个栈,一个用于存储操作数(数字),另一个用于存储运算符,通过按照运算符的优先级和括号的规则来逐步处理表达式,最终得到计算结果。
代码结构及功能解析
solution方法
public static int solution(String expression) {
return calculate(expression);
}
solution方法作为对外的接口,它接收一个表示四则运算表达式的字符串参数expression,然后直接调用calculate方法进行实际的计算,并返回最终的计算结果。
calculate方法
private static int calculate(String expression) {
java.util.Stack<Integer> numStack = new java.util.Stack<>();
java.util.Stack<Character> opStack = new java.util.Stack<>();
int i = 0;
while (i < expression.length()) {
char currentChar = expression.charAt(i);
if (Character.isDigit(currentChar)) {
int num = 0;
while (i < expression.length() && Character.isDigit(currentChar)) {
num = num * 10 + (currentChar - '0');
i++;
if (i < expression.length()) {
currentChar = expression.charAt(i);
}
}
numStack.push(num);
} else if (currentChar == '(') {
opStack.push(currentChar);
i++;
} else if (currentChar == ')') {
while (!opStack.isEmpty() && opStack.peek()!= '(') {
performOperation(numStack, opStack);
}
opStack.pop();
i++;
} else {
while (!opStack.isEmpty() && precedence(currentChar) <= precedence(opStack.peek())) {
performOperation(numStack, opStack);
}
opStack.push(currentChar);
i++;
}
}
while (!opStack.isEmpty()) {
performOperation(numStack, opStack);
}
return numStack.pop();
}
- 首先,创建了两个栈:
numStack用于存储数字,opStack用于存储运算符。然后通过一个循环遍历输入的表达式字符串expression。 - 当遇到数字字符时,通过一个内层循环将连续的数字字符转换为对应的整数,并将其压入
numStack。 - 当遇到左括号
(时,将其直接压入opStack,表示进入一个新的运算子表达式范围。 - 当遇到右括号
)时,会不断从opStack中弹出运算符并执行相应运算(通过调用performOperation方法),直到遇到左括号(,然后将左括号弹出,完成这一层括号内表达式的计算。 - 当遇到运算符(
+、-、*、/)时,会根据运算符的优先级与opStack栈顶运算符的优先级比较。如果当前运算符优先级小于等于栈顶运算符优先级,就先执行栈顶运算符对应的运算(同样通过调用performOperation方法),然后再将当前运算符压入opStack。否则,直接将当前运算符压入opStack。 - 最后,当表达式遍历完后,如果
opStack还有剩余运算符,就依次执行这些运算符对应的运算,直到opStack为空。此时numStack栈顶元素就是表达式的最终计算结果,通过numStack.pop()返回。
performOperation方法
private static void performOperation(java.util.Stack<Integer> numStack, java.util.Stack<Character> opStack) {
char op = opStack.pop();
int right = numStack.pop();
int left = numStack.pop();
if (op == '+') {
numStack.push(left + right);
} else if (op == '-') {
numStack.push(left - right);
} else if (op == '*') {
numStack.push(left * right);
} else if (op == '/') {
numStack.push(left / right);
}
}
这个方法用于执行具体的四则运算操作。它从opStack中弹出一个运算符,从numStack中弹出两个操作数(先弹出的是右操作数,后弹出的是左操作数),然后根据弹出的运算符进行相应的加、减、乘、除运算,并将结果压回numStack。
precedence方法
private static int precedence(char op) {
if (op == '+' || op == '-') {
return 1;
} else if (op == '*' || op == '/') {
return 2;
}
return 0;
}
precedence方法用于确定运算符的优先级。它接收一个运算符字符作为参数,返回该运算符的优先级值。其中+、-的优先级为1,*、/的优先级为2,其他情况返回0。这个优先级值在calculate方法中用于比较运算符的优先级,以决定运算的执行顺序。