我想知道是否有一种方法可以使用两个栈在单次遍历中解决中缀表达式?
这些栈可以一个用于操作符,另一个用于运算元...
通过逆波兰算法的标准方法是将中缀表达式转换为后缀表达式(逆波兰表示法),然后再求解。我不想先将表达式转换为后缀表达式。
如果表达式类似于2*3-(6+5)+8
,应该如何求解?
我想知道是否有一种方法可以使用两个栈在单次遍历中解决中缀表达式?
这些栈可以一个用于操作符,另一个用于运算元...
通过逆波兰算法的标准方法是将中缀表达式转换为后缀表达式(逆波兰表示法),然后再求解。我不想先将表达式转换为后缀表达式。
如果表达式类似于2*3-(6+5)+8
,应该如何求解?
虽然有点晚,但这就是答案。
使用两个栈:
运算符栈
{ 用于存放运算符和括号 }。操作数栈
。如果存在字符需要读取:
操作数
,则将其推入 操作数栈
;如果字符是 (
,则将其推入 运算符栈
。运算符
:
运算符栈
的顶部优先级不低于此字符,就执行以下步骤。运算符栈
中弹出 运算符
。操作数栈
中弹出两个 操作数
(op1
和 op2
)。op1 op op2
存储在 操作数栈
上,回到 2.1 步骤。)
,则执行与 2.2 - 2.4 相同的操作,直到遇到 (
。否则(没有更多字符需要读取):
运算符栈
不为空。操作数
,并将 op1 op op2
推入 操作数栈
。从 操作数栈
返回顶部值。
在这个链接中提供的方法非常好。
让我引用一下源文:
We will use two stacks:
Operand stack: to keep values (numbers) and
Operator stack: to keep operators (+, -, *, . and ^).
In the following, “process” means, (i) pop operand stack once (value1) (ii) pop operator stack once (operator) (iii) pop operand stack again (value2) (iv) compute value1 operator value2 (v) push the value obtained in operand stack.
Algorithm:
Until the end of the expression is reached, get one character and perform only one of the steps (a) through (f):
(a) If the character is an operand, push it onto the operand stack.
(b) If the character is an operator, and the operator stack is empty then push it onto the operator stack.
(c) If the character is an operator and the operator stack is not empty, and the character's precedence is greater than the precedence of the stack top of operator stack, then push the character onto the operator stack.
(d) If the character is "(", then push it onto operator stack.
(e) If the character is ")", then "process" as explained above until the corresponding "(" is encountered in operator stack. At this stage POP the operator stack and ignore "(."
(f) If cases (a), (b), (c), (d) and (e) do not apply, then process as explained above.
When there are no more input characters, keep processing until the operator stack becomes empty. The values left in the operand stack is the final result of the expression.
以下是我在Java中进行中缀表达式评估的尝试。如果您发现任何错误,请告诉我:)
import java.util.*;
public class ArithmeticExpressionEvaluation {
public static void main(String[] args) {
Scanner readExpression = new Scanner(System.in);
System.out.print("Enter the expression: ");
String expression = readExpression.nextLine();
System.out.println(expression);
System.out.println("Result: " + calculateExpression(expression));
}
public static long calculateExpression(String expression) {
Stack<Long> operandStack = new Stack<>();
Stack<Character> operatorStack = new Stack<>();
if (!isValidExpression(expression)) {
System.out.println("Not a valid expression to evaluate");
return 0;
}
int i = 0;
String currentInteger = null;
while (i < expression.length()) {
// System.out.println(expression.charAt(i));
if (expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
currentInteger = expression.charAt(i) + "";
i++;
while (i != expression.length() && (expression.charAt(i) >= '0' && expression.charAt(i) <= '9')) {
currentInteger = currentInteger + expression.charAt(i);
i++;
}
operandStack.push(Long.parseLong(currentInteger));
} else {
if (expression.charAt(i) == ')') {
while (operatorStack.peek() != '(') {
performArithmeticOperation(operandStack, operatorStack);
}
operatorStack.pop();
} else {
Character currentOperator = expression.charAt(i);
Character lastOperator = (operatorStack.isEmpty() ? null : operatorStack.peek());
if (lastOperator != null && checkPrecedence(currentOperator, lastOperator)) {
performArithmeticOperation(operandStack, operatorStack);
}
operatorStack.push(expression.charAt(i));
}
i++;
}
}
while (!operatorStack.isEmpty()) {
performArithmeticOperation(operandStack, operatorStack);
}
// System.out.println(Arrays.toString(operandStack.toArray()));
// System.out.println(Arrays.toString(operatorStack.toArray()));
return operandStack.pop();
}
public static void performArithmeticOperation(Stack<Long> operandStack, Stack<Character> operatorStack) {
try {
long value1 = operandStack.pop();
long value2 = operandStack.pop();
char operator = operatorStack.pop();
long intermediateResult = arithmeticOperation(value1, value2, operator);
operandStack.push(intermediateResult);
} catch (EmptyStackException e) {
System.out.println("Not a valid expression to evaluate");
throw e;
}
}
public static boolean checkPrecedence(Character operator1, Character operator2) {
List<Character> precedenceList = new ArrayList<>();
precedenceList.add('(');
precedenceList.add(')');
precedenceList.add('/');
precedenceList.add('*');
precedenceList.add('%');
precedenceList.add('+');
precedenceList.add('-');
if(operator2 == '(' ){
return false;
}
if (precedenceList.indexOf(operator1) > precedenceList.indexOf(operator2)) {
return true;
} else {
return false;
}
}
public static long arithmeticOperation(long value2, long value1, Character operator) {
long result;
switch (operator) {
case '+':
result = value1 + value2;
break;
case '-':
result = value1 - value2;
break;
case '*':
result = value1 * value2;
break;
case '/':
result = value1 / value2;
break;
case '%':
result = value1 % value2;
break;
default:
result = value1 + value2;
}
return result;
}
public static boolean isValidExpression(String expression) {
if ((!Character.isDigit(expression.charAt(0)) && !(expression.charAt(0) == '('))
|| (!Character.isDigit(expression.charAt(expression.length() - 1)) && !(expression.charAt(expression.length() - 1) == ')'))) {
return false;
}
HashSet<Character> validCharactersSet = new HashSet<>();
validCharactersSet.add('*');
validCharactersSet.add('+');
validCharactersSet.add('-');
validCharactersSet.add('/');
validCharactersSet.add('%');
validCharactersSet.add('(');
validCharactersSet.add(')');
Stack<Character> validParenthesisCheck = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
if (!Character.isDigit(expression.charAt(i)) && !validCharactersSet.contains(expression.charAt(i))) {
return false;
}
if (expression.charAt(i) == '(') {
validParenthesisCheck.push(expression.charAt(i));
}
if (expression.charAt(i) == ')') {
if (validParenthesisCheck.isEmpty()) {
return false;
}
validParenthesisCheck.pop();
}
}
if (validParenthesisCheck.isEmpty()) {
return true;
} else {
return false;
}
}
}
---- 这是针对没有括号的表达式 ----
仅适用于具有2个运算符的基本表达式
创建一个空的运算符栈 创建一个空的操作数栈 从字符串表达式中创建一个字符数组 对于每个字符 4.1 如果它是一个数字 将它添加到操作数栈中 4.2 如果它是一个运算符 当运算符栈为空,且当前运算符的优先级小于运算符栈顶的运算符时 { 弹出一个操作数 (v1) 弹出第二个操作数 (v2) 弹出一个运算符 (p) 计算 v2 p v1 (最先被推入的数字将最后被弹出) 将结果压入操作数栈中 } 如果运算符栈为空,则将运算符添加到栈中 在读取完所有字符之后 5.1 当运算符栈不为空时 同4.2中描述的循环过程 返回最终结果