表达式求值需要利用栈进行计算
- 前缀表达式: 又称波兰表达式,由右向左遍历表达式,遇到数字就压入栈,遇到运算符就连续弹出两个栈顶元素,用【第一个栈顶元素,运算符,第二个栈顶元素】计算新值压入栈。
- 后缀表达式: 又称逆波兰表达式,由左向右遍历表达式,遇到数字就压入栈,遇到运算符就连续弹出两个栈顶元素,用【第二个栈顶元素,运算符,第一个栈顶元素】计算新值压入栈。
- 中缀表达式: 中缀表达式要记录运算符,遇到一个"(“,就要找到所有该括号中的表达式,递归遍历。有左向右遍历表达式,初始化运算符为”+":
- 如果是数字,检测下一个字符是否为数字,如果是就与当前字符拼接,如果不是,根据运算符压入新的值。(如果操作符是"-"就要压入负值)
- 如果是"(",就递归遍历。
- 如果是运算符,就更新运算符的值。
public class Test {
public static void main(String[] args){
String preOrder = "+3*2+1*2+/(-4)-867";
String inOrder = "3+2*(1+2*(-4/(8-6)+7))";
String postOrder = "3212(-4)86-/7+*+*+";
Test t = new Test();
System.out.println("前缀表达式(波兰表达式)的计算结果是:"+t.preExpression(preOrder));
System.out.println("中缀表达式的计算结果是:"+t.inExpression(inOrder));
System.out.println("后缀表达式(逆波兰表达式)的计算结果是:"+t.postExpression(postOrder));
}
public int preExpression(String expression){
//由右向左遍历,将数字压入栈,遇到运算符就连续弹出两个栈顶元素进行运算
Deque<Integer> stack = new ArrayDeque<>();
for(int i=expression.length()-1;i>=0;i--){
char c = expression.charAt(i);
if(c==')'){
int j=i;
while (expression.charAt(i)!='('){
i--;
}
int tmp = Integer.parseInt(expression.substring(i+1,j));
stack.push(tmp);
}else if(c>='0' && c<='9'){
int tmp = Integer.parseInt(String.valueOf(c));
stack.push(tmp);
}else if(c == '+'){
int a = stack.pop();
int b = stack.pop();
stack.push(a+b);
}else if(c == '-'){
int a = stack.pop();
int b = stack.pop();
stack.push(a-b);
}else if(c == '*'){
int a = stack.pop();
int b = stack.pop();
stack.push(a*b);
}
else if(c == '/'){
int a = stack.pop();
int b = stack.pop();
stack.push(a/b);
}
}
return stack.pop();
}
public void convertNum(int num,Deque<Character> opStack,Deque<Integer> numStack){
char op = opStack.pop();
if(op=='+') numStack.push(num);
else if(op=='-') numStack.push(-num);
else if(op=='/') numStack.push(numStack.pop()/num);
else if(op=='*') numStack.push(numStack.pop()*num);
}
public void convertNum(int num,char op,Deque<Integer> numStack){
if(op=='+') numStack.push(num);
else if(op=='-') numStack.push(-num);
else if(op=='/') numStack.push(numStack.pop()/num);
else if(op=='*') numStack.push(numStack.pop()*num);
}
public int inExpression(String expression){
//中缀相对于前后缀,多了对括号的处理,括号的优先级最高,然后是*/,最后是+-
//由于可能出现负值,所以遇到减号,就将其与后面数字一起加入数字栈,将减法看作加法
Deque<Integer> numStack = new ArrayDeque<>();
char op = '+';
for(int i=0;i<expression.length();i++){
char c = expression.charAt(i);
if(Character.isDigit(c)){
int num = 0;
while(i<expression.length() && Character.isDigit(expression.charAt(i))){
num = num * 10+expression.charAt(i)-'0';
i++;
}
convertNum(num,op,numStack);
i--;
}else if(c == '('){
//记录(的个数
int count = 1;
int j = i+1;
while(j<expression.length() && count>0){
if(expression.charAt(j) == '(') count++;
else if(expression.charAt(j) == ')') count--;
j++;
}
int num = inExpression(expression.substring(i+1,j-1));
convertNum(num,op,numStack);
i = j-1;
}else{
op = c;
}
}
int ans = 0;
while(!numStack.isEmpty()) ans+=numStack.pop();
return ans;
}
public int postExpression(String expression){
//由左向右遍历,将数字压入栈,遇到运算符就连续弹出两个栈顶元素进行运算
Deque<Integer> stack = new ArrayDeque<>();
for(int i=0;i<expression.length();i++){
char c = expression.charAt(i);
if(c == '('){
int j = i;
while (expression.charAt(i)!=')'){
i++;
}
int tmp = Integer.parseInt(expression.substring(j+1,i));
stack.push(tmp);
}else if(c>='0' && c<='9') {
int tmp = Integer.parseInt(String.valueOf(c));
stack.push(tmp);
}else if(c == '+'){
int a = stack.pop();
int b = stack.pop();
stack.push(b+a);
}else if(c == '-'){
int a = stack.pop();
int b = stack.pop();
stack.push(b-a);
}else if(c == '*'){
int a = stack.pop();
int b = stack.pop();
stack.push(b*a);
}
else if(c == '/'){
int a = stack.pop();
int b = stack.pop();
stack.push(b/a);
}
}
return stack.pop();
}
}