中缀表达式求值
1. 思路:
-
定义两个栈:数栈、符号栈。
-
通过一个索引,遍历表达式。
-
如果发现是数字,就直接入数栈。
-
如果发现是一个符号,则分情况讨论:
(1) 如果发现符号栈为空就直接入栈。
(2) 如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈。
(3) 如果符号栈当前有操作符,就进行比较,如果当前的操作符的优先级小于或等于栈中的操作符,就从数栈中弹出两个数,从符号栈中弹出一个符号,进行运算,将结果入数栈,再将当前的符号入符号栈。 -
当表达式遍历完毕,就顺序的从数栈和符号栈中弹出相应的数和符号,并计算,将结果入数栈。
-
最后数栈中只有一个数字,就是表达式的结果。
2. 注意:处理多位数
- 当处理多位数时,不能发现是一个数就立即入栈,因为可能是多位数。
- 在处理数,需要向表达式的 index 后再看一位,如果是数就进行扫描,如果是符号才入栈。
- 们需要定义一个字符串变量,用于拼接多位数。
3. 代码实现:
public class Calculate {
// 测试
public static void main(String[] args) {
String expression = "100+6*2-2";
int result = calculateExpression(expression);
System.out.println(result);
}
// 计算中缀表达式的值
private static int calculateExpression(String expression) {
// 初始化数字栈
Stack numStack = new Stack(10);
// 初始化符号栈
Stack operatorStack = new Stack(10);
// 指向遍历到表达式的位置
int index = 0;
// 临时存储从数字栈取出的数字
int num1;
int num2;
// 存储从符号栈中取出的运算符
int operator;
// 临时存储表达式遍历到的字符
char temp;
// 用于处理多位数字的字符串
String keepNum = "";
while (true) {
temp = expression.substring(index, index+1).charAt(0);
if (operatorStack.isOperator(temp)) {
//如果是操作符
if (operatorStack.isEmpty()) {
//如果符号栈为空,直接入符号栈
operatorStack.push(temp);
} else {
//如果符号栈不为空
if (operatorStack.priority(temp) > operatorStack.priority(operatorStack.getTopValue())) {
//如果当前操作符优先级高于栈顶操作符优先级,直接入栈
operatorStack.push(temp);
} else {
//如果当前操作符优先级低于栈顶操作符优先级,先取出两个数字,取出栈顶操作符,计算
//将计算结果入数栈,当前操作符入符号栈
num1 = numStack.pop();
num2 = numStack.pop();
operator = operatorStack.pop();
int result = numStack.calculate(num1, num2, operator);
numStack.push(result);
operatorStack.push(temp);
}
}
} else {
//如果是数字
//numStack.push(temp - '0');
//多位数字
keepNum += temp;
if (index == expression.length()-1) {
numStack.push(Integer.parseInt(keepNum));
}else {
if (numStack.isOperator(expression.substring(index+1, index+2).charAt(0))) {
numStack.push(Integer.parseInt(keepNum));
keepNum = "";
}
}
}
index++;
if (index >= expression.length()) {
break;
}
}
while (true) {
if (operatorStack.isEmpty()) {
break;
}
num1 = numStack.pop();
num2 = numStack.pop();
operator = operatorStack.pop();
int result = numStack.calculate(num1, num2, operator);
numStack.push(result);
}
return numStack.pop();
}
}
/**
* 栈类
*/
class Stack {
private int maxSize;
private int[] stack;
private int top = -1;
/**
* 构造器
* @param maxSize 栈大小
*/
public Stack(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
/**
* 判断栈空
* @return 空:true
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断栈满
* @return 满:true
*/
public boolean isFull() {
return top == maxSize -1;
}
/**
* 入栈
* @param value 待入栈数据
*/
public void push(int value) {
if (isFull()) {
System.out.println("栈满!");
return;
}
stack[++top] = value;
}
/**
* 出栈
* @return 出栈数据
*/
public int pop() {
if (isEmpty()) {
System.out.println("栈空!");
System.exit(0);
}
return stack[top--];
}
/**
* 得到栈顶的值
* @return 栈顶值
*/
public int getTopValue() {
return stack[top];
}
/**
* 判断是否为操作符
* @param operator 待判断字符
* @return 是:true
*/
public boolean isOperator(int operator) {
return operator == '+' || operator == '-' || operator == '*' || operator == '/';
}
/**
* 判断操作符优先级
* @param operator 操作符
* @return 优先级
*/
public int priority(int operator) {
if (operator == '*' || operator == '/') {
return 1;
} else {
return 0;
}
}
/**
* 计算结果
* @param num1 值1
* @param num2 值2
* @param operator 运算符
* @return 结果
*/
public int calculate(int num1, int num2, int operator) {
int result = 0;
switch (operator) {
case '+':
result = num2 + num1;
break;
case '-':
result = num2 - num1;
break;
case '*':
result = num2 * num1;
break;
case '/':
result = num2 / num1;
break;
}
return result;
}
}