思路:
1.首先我们需要两个栈,一个是数栈用于存放数,另一个是符号栈用于存放操作符
2.通过一个索引值index,来遍历我们需要计算的表达式
3.当我们遍历表达式的时候,如果我们发现当前遍历到的是数字就将其放入数栈中
4.如果我们发现当前遍历到的是符号,就分如下的情况:
(1)如果符号栈为空,就将当前的操作符入符号栈中
(2)如果符号栈有操作符,就进行比较,如果当前操作符的优先级小于或等于栈中操作符,就需要从数栈中pop出两个数,再从符号栈中pop出一个操作符,进行运算,将得到的结果入数栈中,然后将当前操作符入符号栈,如果当前操作符的优先级大于栈中的操作符,就将当前操作符直接入符号栈。
5.当需要计算的表达式遍历完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运算
6.最后在数栈中就只有一个数字,就是表达式的值
public class Solution {
public static void main(String[] args) {
Solution sol = new Solution();
//int res = sol.calExp("1+2*4/2-1+5");
int res = sol.calExp("3+5*8-6");
System.out.println(res);
}
public int calExp(String express){
LinkedList<Character> op = new LinkedList<>();
LinkedList<Integer> data = new LinkedList<>();
for (int i = 0; i < express.length(); i++) {
char c = express.charAt(i);
//如果是数据
if(Character.isDigit(c)){
//入操作数栈
data.addFirst(Integer.parseInt(String.valueOf(c)));
}else{
Character stackTopOp = null;
//如果操作符栈不为空,获取操作符栈顶元素
if(!op.isEmpty()){
stackTopOp = op.getFirst();
}
//如果操作符栈为空 或者 当前操作符的优先级高于操作符栈顶元素的优先级
if(op.isEmpty() ||getOpPriority(c,stackTopOp)){
//当前操作符入栈
op.addFirst(c);
}else{
//取出操作符栈顶元素
Character opTop = op.removeFirst();
//取出操作数栈顶两个元素
int b = data.removeFirst();
int a = data.removeFirst();
//计算
int resTmp = calculate(a, b, opTop);
//将计算完的结果入栈
data.addFirst(resTmp);
//最后将当前操作符入栈
op.addFirst(c);
}
}
}
//最后遍历整个操作符栈,此时操作符栈中的优先级都是一致的。
while (!op.isEmpty()) {
Character opTop = op.removeFirst();
Integer b = data.removeFirst();
Integer a = data.removeFirst();
int res = calculate(a, b, opTop);
data.addFirst(res);
}
//最后操作数栈中只剩一个元素,就是计算结果
return data.getFirst();
}
/**
* 判断两个运算符之间的优先级
* 如果c1运算符优先级大于c2运算符优先级,则返回true
* 否则返回false
* @param c1
* @param c2
* @return
*/
private boolean getOpPriority(Character c1,Character c2){
if((c1.equals('*') || c1.equals('/')) &&
(c2.equals('+') || c2.equals('-'))){
return true;
}else{
return false;
}
}
public int calculate(int a,int b, char op){
switch (op){
case '*':
return a*b;
case '/':
return a/b;
case '+':
return a+b;
case '-':
return a-b;
default:
throw new IllegalArgumentException();
}
}
}