定义:
中缀表达式:
我们平时写的数学表达式一般为中缀表达式,如“5+2*(3*(3-1*2+1))”,直接拿中缀表达式直接让计算机计算表达式的结果并不能做到。
后缀表达式:
把中缀表达表达式“5+2*(3*(3-12+1))”转化“523312-1+**+”这样的形式,就是后缀表达式。这种记法叫做后缀(postfix)或逆波兰(reverse Polish)记法。计算这个问题最容易的方法就是使用一个栈。
具体实现:
(1)方法概述:
1.从左到右进行遍历。
2.运算数,直接输出。
3.左括号,直接压入堆栈,括号是最高优先级,无需比较,入栈后优先级降到最低,确保其他符号正常入栈。
4.右括号,(意味着括号已结束)不断弹出栈顶运算符并输出直到遇到左括号(弹出但不输出)。
5.运算符,将该运算符与栈顶运算符进行比较
如果优先级高于栈顶运算符则压入堆栈(该部分运算还不能进行)。
如果优先级低于等于栈顶运算符则将栈顶运算符弹出并输出,然后比较新的栈顶运算符。
低于弹出意味着前面部分可以运算,先输出的一定是高优先级运算符,等于弹出是因为同等优先级,从左到右运算。
直到优先级大于栈顶运算符或者栈空,再将该运算符入栈。
6.如果对象处理完毕,则按顺序弹出并输出栈中所有运算符。
(2)转换举例:
输入:(2*(9+6/3-5)+4)
操作 | 说明 | 栈 | 输出 |
---|---|---|---|
读取( | 把(直接压入栈 | ( | ---- |
读取2 | 把操作数直接输出 | ( | 2 |
读取* | 把*直接压入栈 | (* | 2 |
读取( | 把(直接压入栈 | (*( | 2 |
读取9 | 把操作数直接输出 | (*( | 29 |
读取+ | 把+直接压入栈 | (*(+ | 29 |
读取6 | 把操作数直接输出 | (*(+ | 296 |
读取/ | 栈顶元素为+,优先级低于/,把操作符压入栈中 | (*(+/ | 296 |
读取3 | 把操作数直接输出 | (*(+/ | 2963 |
读取- | 栈顶元素为/,优先级高于-,以此弹出/和+,到 ( 停止,把操作符压入栈中 | (*(- | 2963/+ |
读取5 | 把操作数直接输出 | (*(- | 2963/+5 |
读取) | 从栈中弹出-到输出,遇到第一个 ( 停止,把 ( 弹出栈 | (* | 2963/+5- |
读取+ | 栈顶元素为*,优先级高于+,以此弹出 ,到 ( 停止,把操作符压入栈中 | (+ | 2963/+5-* |
读取4 | 把操作数直接输出 | (+ | 2963/+5-*4 |
读取) | 从栈中弹出+到输出,遇到第一个 ( 停止,把 ( 弹出栈 | – | 2963/+5-*4+ |
(3)代码实现
import java.util.Stack;
public class Main {
static Stack<Character> op = new Stack<>();
public static Float getv(char op, Float f1, Float f2){
if(op == '+') return f2 + f1;
else if(op == '-') return f2 - f1;
else if(op == '*') return f2 * f1;
else if(op == '/') return f2 / f1;
else return Float.valueOf(-0);
}
public static float calrp(String rp){
Stack<Float> v = new Stack<>();
char[] arr = rp.toCharArray();
int len = arr.length;
for(int i = 0; i < len; i++){
Character ch = arr[i];
if(ch >= '0' && ch <= '9') {
v.push(Float.valueOf(ch - '0'));
} else v.push(getv(ch, v.pop(), v.pop()));
}
return v.pop();
}
public static String getrp(String s){
char[] arr = s.toCharArray();
int len = arr.length;
String out = "";
for(int i = 0; i < len; i++){
char ch = arr[i];
if(ch == ' ') {
continue;
}
if(ch >= '0' && ch <= '9') {
out+=ch;
continue;
}
if(ch == '(') {
op.push(ch);
}
if(ch == '+' || ch == '-'){
while(!op.empty() && (op.peek() != '('))
out+=op.pop();
op.push(ch);
continue;
}
if(ch == '*' || ch == '/'){
while(!op.empty() && (op.peek() == '*' || op.peek() == '/'))
out+=op.pop();
op.push(ch);
continue;
}
if(ch == ')'){
while(!op.empty() && op.peek() != '(')
out += op.pop();
op.pop();
continue;
}
}
while(!op.empty()) out += op.pop();
return out;
}
}