前缀、中缀、后缀表达式(逆波兰表达式)
前缀表达式(波兰表达式)
- 前缀表达式的运算符位于操作数之前,例如:(1+2)x(5+6)对应的前缀表达式为:+ x + 1 2 5 6
- 前缀表达式的计算机求值:从右至左扫描表达式,遇到数字时,将数字入数栈,遇到运算符时,弹出数栈的两个数进行计算(因为是从右至左扫描,所以后入栈的数字在运算符前面,即栈顶的数字在前,次顶的数字灾在后),然后将结果入数栈,重复进行直到遍历完表达式,最后一次计算的结果就是表达式的值
中缀表达式
- 中缀表达式就是常见的运算表达式,如(1+2)x(5+6)
- 中缀表达式的求值对人来说很熟悉,但是对于计算机来说不好操作,因此在使用计算机计算结果时,通常先将表达式转成其他的表达式再进行求值(通常转成后缀表达式)
后缀表达式
- 后缀表达式又称逆波兰表达式,与前缀表达式相似,不过运算符在操作数之后,如(1+2)x(5+6) 的后缀表达式为:1 2 + 5 6 + x
- 后缀表达式的计算机求值:从左至右扫描表达式,遇到数字时,将数字压入数栈,遇到符号时,弹出栈顶的两个数进行计算(因为是从左至右扫描,所以先入栈的数字在运算符前面,即次顶的数字在前,栈顶的数字在后),然后将结果入栈,依次直到遍历完表达式,最后的结果就是表达式的值
逆波兰计算器
中缀表达式转后缀表达式分析
- 初始化两个栈,一个栈用来存运算符s1,一个栈用来存转换的中间结果s2
- 从左至右扫描表达式
- 遇到操作数时,将数压入结果栈s2
- 遇到运算符时,如果符号栈为空,或者栈顶为左括号"(",则直接压入符号栈;如果符号栈不为空,则比较当前符号和栈顶符号的优先级,如果当前符号的优先级更高则也压入符号栈,否则将符号栈中的符号弹出压入结果栈,然后继续对比符号栈的栈顶元素直到栈为空或优先级低于当前符号
- 遇到括号时,如果是左括号,直接入符号栈;如果是右括号,则依次弹出符号栈中的符号并压入结果栈中直到弹出左括号
- 遍历表达式结束后,依次将符号栈中的元素弹出并压入结果栈中
- 最后结果栈中的元素弹出的逆序就是该中缀表达式对应的后缀表达式
代码实现
public class PolandCaculator {
public static void main(String args[]) {
System.out.println(caculate("1+((2+3)*4)-5*2"));
}
private static List<String> conversion(String infixExpression) {
Stack<String> operStack = new Stack<>();
List<String> result = new ArrayList<>();
int length = infixExpression.length();
String current;
for (int i = 0; i < length; i++) {
current = infixExpression.substring(i, i + 1);
if (current.matches("\\d")) {
result.add(current);
while (i != length - 1 && (current = infixExpression.substring(i + 1, i + 2)).matches("\\d")) {
result.set(result.size() - 1, String
.valueOf(Integer.parseInt(result.get(result.size() - 1)) * 10 + Integer.parseInt(current)));
i++;
}
} else {
if (operStack.isEmpty()) {
operStack.push(current);
} else {
switch (current) {
case "(":
operStack.push(current);
break;
case ")":
while (!operStack.peek().equals("(")) {
result.add(operStack.pop());
}
operStack.pop();
break;
default:
while (!operStack.isEmpty()
&& !operStack.peek().equals("(")
&& Operation.getPriority(operStack.peek()) >= Operation.getPriority(current)) {
result.add(operStack.pop());
}
operStack.push(current);
}
}
}
}
while (!operStack.isEmpty()) {
result.add(operStack.pop());
}
return result;
}
public static int caculate(String suffixExpression) {
Stack<Integer> numStack = new Stack<>();
for (String str : conversion(suffixExpression)) {
if (str.matches("\\d+")) {
numStack.push(Integer.parseInt(str));
} else {
numStack.push(cal(numStack.pop(), numStack.pop(), str));
}
}
return numStack.pop();
}
private static int cal(int num1, int num2, String oper) {
switch (oper) {
case "+":
return num1 + num2;
case "-":
return num2 - num1;
case "*":
return num1 * num2;
case "/":
return num2 / num1;
}
throw new RuntimeException("运算符有误");
}
}
class Operation {
private static final int ADD = 1;
private static final int SUB = 1;
private static final int MUL = 2;
private static final int DIV = 2;
public static int getPriority(String opr) {
switch (opr) {
case "+":
return ADD;
case "-":
return SUB;
case "*":
return MUL;
case "/":
return DIV;
default:
throw new RuntimeException("输入有误");
}
}
}