Java实现计算表达式的值

需求

已知一个只含有()、+ 、-、*、\这五种操作符,数字只是整数,并且空格隔开的表达式字符串,求表达式的值。
例如:
( 3 + 4 ) * 5 - 6
结果为29

解题思路

给定表达式为中缀表达式,将其转为后缀表达式(逆波兰表达式)然后使用逆波兰表达式求解值。
逆波兰表达式求解值得思路:

  1. 遍历表达式,遇到数值则入栈,遇到计算符则从栈中弹出两个元素然后将计算结果压入栈中。做减和除法运算的时候一定要注意顺序,都是拿次栈顶去减/除栈顶元素。
  2. 遍历完毕后栈中的元素就是表达式的结果值。

Java实现

1. 中缀表达式转逆波兰表达式

思路:
首先需要一个栈operator用来存放计算符号和左括号(;
还需要一个集合来存放逆波兰表达式(这个集合可以是list、stack等)。
遍历表达式,得到值为item:

  1. 如果item为数值,则直接将item入中间结果集合中;
  2. 否则如果为"(",则直接入栈
  3. 否则如果为")",栈顶元素不是"(“时,将栈中元素不断弹出然后加入到中间结果集合中。结束之后将栈顶的”("弹出。这一步的目的是为了去括号
  4. 否则,当栈不为空并且栈顶元素的优先级 >= item的优先级时,不断的将栈中的元素弹出并添加到中间结果集合中。循环结束,将item入栈。
    遍历结束后,集合中就是逆波兰表达式。

2. 计算逆波兰表达式的值

前提:

  1. 整数相除只取整数部分;
  2. 结果一定为整数(这里可以根据需求改成浮点型数据,并且加入除0判断并抛出异常)。
    逆波兰表达式求值的思路前面已经讲过,这里不再敖述了。

3. 代码实现

public class CalculateExpression {
    public static void main(String[] args) {
        String expression = "( 3 + 4 ) * 5 - 6 - 3 * 3 - 2";
        System.out.println(calculateExpression(expression));//结果18
    }
    public static int calculateExpression(String expression){
        Stack<String> operator = new Stack<>();//操作符栈
        List<String> list = new ArrayList<>();//结果集
        String[] s = expression.split(" ");//表达式集合
        //遍历表达式
        for (int i = 0; i < s.length; i++) {
            if (s[i].matches("\\d+"))//正则表达式匹配数字,对应思路1
                list.add(s[i]);
            else if (s[i].equals("(")){//对应思路2
                operator.push(s[i]);
            }else if (s[i].equals(")")){//对应思路3
                while (!operator.peek().equals("(")){
                    list.add(operator.pop());
                }
                operator.pop();
            }else{//对应思路4
                while (!operator.isEmpty() && priority(operator.peek()) >= priority(s[i])){
                    list.add(operator.pop());
                }
                operator.push(s[i]);
            }
        }
        while (!operator.isEmpty())
            list.add(operator.pop());
        Stack<Integer> nums = new Stack<>();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals("+")){
                nums.push(nums.pop() + nums.pop());
            }else if (list.get(i).equals("-")){
                nums.push(-(nums.pop() - nums.pop()));
            }else if (list.get(i).equals("*")){
                nums.push(nums.pop() * nums.pop());
            }else if (list.get(i).equals("/")){
                int num1 = nums.pop();
                int num2 = nums.pop();
                nums.push(num2 / num1);
            } else
                nums.push(Integer.parseInt(list.get(i)));
        }
        return nums.pop();//弹出栈中元素返回结果
    }
    //计算符优先级
    public static int priority(String oper){
        if (oper.equals("+") || oper.equals("-"))
            return 0;
        else if (oper.equals("*") || oper.equals("/"))
            return 1;
        else return -1;
    }
}

总结

表达式如果不带括号,只需要两个栈就能够完成结果的计算,不需要将表达式转逆波兰表达式这步操作。
但是逆波兰表达式的计算思路简单易懂,而且能做到一劳永逸所以我们可以使用这种思路来计算表达式的值。
表达式值的计算涉及到大量关于栈这种基础数据结构的操作,对栈的使用是一个非常好的练习。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值