栈——逆波兰表达式
完成一个逆波兰计算器,需要完成如下任务:
- 输入一个逆波兰表达式(后缀表达式),使用栈(Stack), 计算其结果
- 支持小括号和多位数整数
思路分析
计算:(3+4)* 5 - 6。
- 首先:得到他的后缀表达式为:3 4 + 5 * 6 -
- 逆波兰表达式求值步骤:
1. 从左至右扫描,将3和4push进栈
2. 遇到+运算符,pop出4和3,计算出3+4的值得到7,再将7push进栈
3. 将5入栈
4. 接下来是 * 运算,pop出5和7得到35,将35push进栈
5. 让6入栈
6. 最后是-运算符,计算出35-6的值为29,把29push进栈
7. 此时,栈中只有一个唯一的值,也是逆波兰表达式的解。
代码实现:
整体思路其实最主要的就是两点:(1)取出数据(2)进行计算
而我们可以利用ArrayList来存储逆波兰表达式,而利用栈的pop和push功能来取出和存储计算后的数据。
- 将一个逆波兰表达式以字符串的格式放入ArrayList中
public static List<String> getListString(String suffixExpression){
String[] split = suffixExpression.split(" ");
ArrayList<String> list = new ArrayList<>();
for(String s : split){
list.add(s);
}
return list;
}
- 利用栈,进行计算
public static int caculate(List<String> ls){
//此处需要利用栈的pop和push功能进行参与计算
Stack<String> stack = new Stack<>();
//遍历列表ls
for(String s:ls){
if (s.matches("\\d+")){//使用正则表达式,匹配多个数据
//将匹配到的数据入栈
stack.push(s);
}else {
//pop出两个数,运算完后再入栈
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int res = 0;
if("+".equals(s)){
res = num1 + num2;
}else if ("-".equals(s)){
res = num2 - num1;
}else if ("*".equals(s)){
res = num1 * num2;
}else if ("/".equals(s)){
res = num2 / num1;
}else {
System.out.println("输入的运算符有误~");
}
stack.push(res + "");
}
}
return Integer.parseInt(stack.pop());
}
因为,ArrayList的泛型以及其存储的内容都是String类型的,而我们最后计算得到的结果是int类型的,因此需要通过Integer.parseInt()来将字符串转换成数据(包装类和String之间的类型转换)。
- 主函数测试:以:(4*5)-8+60+8/2为例,正确答案应该为76.
public class PolandNotation {
public static void main(String[] args) {
String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";//为了方便,将逆波兰表达式的数字和符号使用空格隔开
//思路
/**
* 1.先将30 4 + 5 * 6 -放到String类型的ArrayList中
* 2.将ArrayList传递给一个方法,遍历时候配合栈完成计算
*/
List<String> list = getListString(suffixExpression);
int caculate = caculate(list);
System.out.println("最终计算结果为:" + caculate);
}
}
- 结果如图:
通过代码可以发现,逆波兰表达式,利用ArrayList的存储以及栈的pop/push的功能实现计算器的效果,不仅代码量小于中缀表达式的计算方法,而且处理问题的多样性也大于中缀表达式。