1. 后序(逆波兰)
对形如 ABC*+
的后序表达式进行求值,所有操作数均为 0 - 9
的整数,操作符包含 +、-、*、/
,其中 +、-
均为二元操作符
import java.util.Stack;
/**
* 后序表达式求值
*/
public class PostfixSolution {
private Stack<Integer> result = new Stack<>();
private void calculate(char operator) {
int right = result.pop();
int left = result.pop();
switch (operator) {
case '+':
result.push(left + right);
break;
case '-':
result.push(left - right);
break;
case '*':
result.push(left * right);
break;
case '/':
result.push(left / right);
break;
default:
System.exit(1);
break;
}
}
public int solve(String postfix) {
char[] array = postfix.toCharArray();
for (int i = 0; i < array.length; i++) {
if (Character.isDigit(array[i])) {
result.push(array[i] - '0');
} else {
calculate(array[i]);
}
}
return result.pop();
}
public static void main(String[] args) {
System.out.println(new PostfixSolution().solve("32+"));
}
}
2. 中序
中序表达式求值一般可以分为两步,
- 中序表达式转后序
- 后序求值
两步合并为一步操作如下:
import java.util.Stack;
/**
* 中缀表达式(含括号)求值
*/
public class InfixSolution {
private static Stack<Integer> result = new Stack<>();
private static Stack<Character> operator = new Stack<>();
private static void calculate(char operator) {
int right = result.pop();
int left = result.pop();
switch (operator) {
case '+':
result.push(left + right);
break;
case '-':
result.push(left - right);
break;
case '*':
result.push(left * right);
break;
case '/':
result.push(left / right);
break;
default:
System.exit(1);
break;
}
}
private static int getPriority(char operator) {
if (operator == '#') {
return 0;
} else if (operator == '('){
return 1;
} else if (operator == '+' || operator == '-') {
return 2;
} else if (operator == '*' || operator == '/') {
return 3;
} else {
return -1;
}
}
/**
* 一般操作顺序:
* 1. 中序 ---> 后序
* 2. 后序求值
* 现将两步合并为一步
* 使用两个栈,分别为最终结果栈 result 与操作符栈 operator,operator 预置优先级最低的 '#'
* 循环遍历中序序列,遇操作数入 result;
* 遇操作符:
* 1. '(': 直接入 operator
* 2. ')': operator 不断退栈并利用该元素计算
* 3. '+、-、*、/': 与 operator 栈顶元素比较,
* 若当前优先级<=栈顶运算符的优先级,则不断退栈并利用该元素计算;
* 否则入 operator
*/
private static void solve(String infix) {
char[] array = infix.toCharArray();
for (int i = 0; i < array.length; i++) {
if (Character.isDigit(array[i])) { // 操作数
result.push(array[i] - '0');
} else {
if (array[i] == '(') {
operator.push(array[i]);
} else if (array[i] == ')') {
char temp = operator.pop();
for (; temp != '('; temp = operator.pop()) {
calculate(temp);
}
} else if (getPriority(array[i]) <= getPriority(operator.peek())) {
char temp = operator.peek();
while (getPriority(array[i]) <= getPriority(temp)) {
calculate(temp);
operator.pop();
temp = operator.peek();
}
} else {
operator.push(array[i]);
}
}
}
if (operator.peek() != '#') {
calculate(operator.pop());
}
System.out.println(result.pop());
}
public static void main(String[] args) {
operator.push('#');
solve("(2+3)*(8-2)");
}
}
3. 前序(波兰)
import java.util.Stack;
/**
* 前序表达式求值
*/
public class PrefixSolution {
private Stack<Integer> result = new Stack<>();
/**
* 由于逆向扫描表达式,所以先退栈的是第一个操作数
*/
private void calculate(char operator) {
int left = result.pop();
int right = result.pop();
switch (operator) {
case '+':
result.push(left + right);
break;
case '-':
result.push(left - right);
break;
case '*':
result.push(left * right);
break;
case '/':
result.push(left / right);
break;
default:
System.exit(1);
break;
}
}
/**
* 扫描从右往左进行
* 遇操作数,入 result
* 遇操作符,从 result 弹出两个操作数进行计算
* 扫描结束后,result 栈顶就是表达式结果
*/
private int solve(String prefix) {
char[] array = prefix.toCharArray();
for (int i = array.length - 1; i >= 0; i--) {
if (Character.isDigit(array[i])) {
result.push(array[i] - '0');
} else {
calculate(array[i]);
}
}
return result.pop();
}
public static void main(String[] args) {
System.out.println(new PrefixSolution().solve("-32"));
}
}