因为中缀表达式对于操作符的优先级很不好计算,就将中缀转成计算机更容易识别的后缀表达式
中缀转后缀表达式写法:
a+b => a b +
a+(b-c) => a b c - +
a+(b-c)*d => a b c - d * +
a+d*(b-c) => a d b c - * +
a=1+3 => a 1 3 + =
后缀表达式(逆波兰表达式)计算规则:
从左向右扫描,遇到操作符就将左边的两个数取出进行运算
然后将结果插入到原来取出两个数的位置,再向右扫描
代码实现:
遇到数字就入数栈,遇到操作符就取出栈顶和次栈顶的数进行运算
然后将结果压入数栈中,这里就不需要操作符栈了,因为每遇到
一个操作符就进行了运算
分割数和操作符并存入链表
public static List<String> getListString(String suffixExpression) {
//将表达式分割
String[] strs = suffixExpression.split(" ");
ArrayList<String> list = new ArrayList<>();
//forEach的参数传递的是一个消费型接口
Arrays.stream(strs).forEach((str) -> {
list.add(str);
});
return list;
}
public static int caculate(List<String> list) {
// 创建一个栈,只需要一个栈,只需要存数字
Stack<String> stack = new Stack<>();
// 遍历list
list.stream().forEach((str) -> {
//这里使用正则表达式来判断是否是数字
if (str.matches("\\d+")) {//匹配的是多位数
//入栈
stack.push(str);
} else {
//从栈中pop两个数并运算,结果再入栈
//先pop出来的是被* 被/数
//后pop出来的是 / -数
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
switch (str) {
case "+":
res = num1 + num2;
break;
case "-":
res = num1 - num2;
break;
case "*":
res = num1 * num2;
break;
case "/":
res = num1 / num2;
break;
default:
throw new RuntimeException("运算符有误");
}
//结果入栈
stack.push(res + "");
}
});
//最后留在stack中的数是运算结果
return Integer.parseInt(stack.pop());
}
原文:https://www.cnblogs.com/fkPrograming/p/14497756.html