逆波兰表达式的运算

问题引入

      我们平常计算的表达式通常为中缀表达式,例如;1+((2+3)*4)+5,而这样的方式对计算机并不友好,对于计算机而言,更好的为前缀表达式和后缀表达式,在这两者之间,对于我们而言,后缀表达式更好理解一些,例如:3 4 + 5 * 6 - ,计算过程如下:
       3 4 + 先运算得到7,然后表达式就变为7 5 * 6 -,继续计算下去
,35 6 -,最后得到29。
      前缀表达式又被称为波兰表达式,而后缀表达式被称为逆波兰表达式。
      接下来就介绍如何用程序来计算逆波兰表达式。

思路分析

      就拿这个例子来说1 2 3 + 4 * + 5 -。
前置准备
      以其为字符串来计算,首先把放入集合中,每一个字符都当作一个字符串,而此时我们还需考虑多位数的计算,如果某表达式为26 + 2,我们不能把它变为2,6,+,2,于是我们在遍历字符串时需要一个中间变量,来记录当前的数,如果当前读到的是符号,就把中间变量放入集合中,同时把中间变量置空,然后把符号放入集合中,依次遍历最后得到盛放逆波兰字符串的集合。
在这里插入图片描述
在这里插入图片描述
具体计算
      当我们成功拿到逆波兰表达式的集合后,开始遍历集合,那么什么类型的数据结构适合运算这个表达式呢?
在这里插入图片描述

      注意,当我们运算+ *法时,弹出栈的数据计算顺序可以随便写,但是当遇见- / 法时,我们需要用栈下面的值-或/上面的值。运算过程的思路就是这样。

具体代码实现

public class PolandNotation {
    public static void main(String[] args) {
        String centerExpression = "1 2 3 + 4 * + 5 -";
        List<String> result = toSuffixExpressionList(centerExpression);
        System.out.println("后缀表达式的结果为: " + calculator(result));
    }
//后缀字符串转集合
    public static List<String> toSuffixExpressionList(String s){
        //定义一个list,存放后缀表达式对应的内容
        List<String> ls = new ArrayList<>();
        int i = 0; //起始索引
        String str = ""; //对多位数的拼接
        char c; //每遍历到一个字符就放入c中
        do {
            if((c = s.charAt(i)) < '0' || (c = s.charAt(i)) > '9') {
                if(c == ' '){ //当字符为空格时跳过
                    i++;
                    continue;
                }
                ls.add("" + c);
                i++;
            } else {
                str = "";
                while (i < s.length() && ((c = s.charAt(i)) >= '0' && (c = s.charAt(i)) <= '9' || (c = s.charAt(i)) == '.')) {
                    str += c;
                    i++;
                }
                ls.add(str);
            }
        } while (i < s.length()) ;
        return ls;
    }
//完成对逆波兰表达式的运算
    public static double calculator(List<String> rpnList) {
        Stack<Double> stack = new Stack<>();
        for (String temp : rpnList) {
            if (!isOper(temp)) {
                stack.push(Double.valueOf(temp));
            } else {
                double num1 = Double.valueOf(stack.pop());
                double num2 = Double.valueOf(stack.pop());

                stack.push(cal(num1, num2, temp));
            }
        }
        return stack.pop();
    }
//判断当前字符是否为符号
    public static boolean isOper(String ch) {
        return ch.equals("+") || ch.equals("-") || ch.equals("*") || ch.equals("/") || ch.equals("(") || ch.equals(")");
    }
//计算方法
    public static double cal(double num1, double num2, String oper) {
        //用于存放计算的结果
        double res = 0.0;
        switch (oper) {
            case "+":
                res = num1 + num2;
                break;
            case "-":
                res = num2 - num1; //注意顺序
                break;
            case "*":
                res = num1 * num2;
                break;
            case "/":
                if(num1 == 0){
                    throw new RuntimeException("被除数不能为0");
                }
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
} 
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值