后缀表达式模拟逆波兰计算器详解
思路分析
- 先将一个表达式,即要计算的式子,也就是中缀表达式,转换为后缀表达式,每一个字符中间用空格隔开,方便字符串的分割
- 将后缀表达式按照空格分割后存储到集合中,集合很方便遍历、存和取
- 定义堆栈用来辅助计算
- 然后遍历集合,如果取到的是数字,则直接入栈,如果取到的是运算符,则进行相应的运算
- 将每次计算的结果再入栈
- 集合中所有元素遍历完毕后,堆栈中存储的是计算的结果,返回即可
- 源码及分析如下
源码及详解
public static void main(String[] args) {
//模拟逆波兰计算机 例如计算 (3 + 4) * 5 - 6 ,其对应的后缀表达式为3 4 + 5 * 6 -
//已知后缀表达式,中间用空格隔开,方便分割
String expression = "(35 + 4) * 52 - 66";
String suffixExpression = "35 4 + 52 * 66 -";
//测试分割的方法
List<String> listString = getListString(suffixExpression);
//System.out.println(listString);
//测试OK
int res = calculate(listString);
System.out.println(expression + " = " + res);
}
//编写一个方法将后缀表达式中的所有字符分割并存储在一个ArrayList集合中
/**
*
* @param suffixExpression 后缀表达式
* @return 拆分的结果
*/
public static List<String> getListString(String suffixExpression) {
//定义一个集合保存各个字符
ArrayList<String> list = new ArrayList<>();
//将后缀表达式按照空格分割
String[] strings = suffixExpression.split(" ");
//将分割后的字符串加入到集合
for (String string : strings) {
list.add(string);
}
return list;
}
/**
* 编写后缀表达式的计算方法
*
* @param list 集合中保存要计算的数字和操作符
* @return 计算的结果
*/
public static int calculate(List<String> list) {
//定义栈用来辅助计算
Stack<String> stack = new Stack<>();
//遍历集合
for (String item : list) {
//使用正则判断遍历出的是数字还是符号
if (item.matches("\\d+")) {
//如果是数字,则直接入栈
stack.push(item);
} else {
//如果是符号,则从栈中弹出两个数进行计算
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
//调用计算的方法
int res = calculateByNumAndOperation(num2, num1, item.charAt(0));
//将计算的结果再入栈
stack.push(res + "");
}
}
//运算结束后留在栈底的就是计算的结果,返回即可
return Integer.parseInt(stack.pop());
}
/**
* 通过数字和操作符计算的方法
*
* @param num1 数字1
* @param num2 数字2
* @param operation 运算符
* @return 计算的结果
*/
public static int calculateByNumAndOperation(int num1, int num2, char operation) {
//定义变量保存运算返回的结果
int res = 0;
switch (operation) {
case '+':
res = num1 + num2;
break;
//减法注意运算顺序
case '-':
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
//除法也要注意运算顺序
res = num2 / num1;
break;
default:
throw new RuntimeException("运算符有误~~");
}
return res;
}