算法 -- 双栈算术表达式求值算法

最近在学习算法时候,看到一个双栈算术表达式求值算法,挺启发我的;平常大家在写代码的时候要写表达式的时候,基本都是直接 (1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) );这样程序会帮你的自动计算出结果,大家有没用想过这程序是如何一步一步计算并得出你需要的值,今天讲一个简单例子,可以帮助大家很好的了解双栈算术表达式求值算法是什么。

首先,为了简单化的解释该算法,我们定义一个未省略括号的表达式:(1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )

算法思路

双栈算术表达式求值算法是由E.W.Dijkstra在上个世纪60年代发明的一个很简单的算法,用两个栈【一个用来保存运算符、一个用来保存操作数】来完成对一个表达式的运算。其实整个算法思路很简单:

  • 无视左括号
  • 将操作数压入操作数栈
  • 将运算符压入运算符栈
  • 在遇到右括号的时候,从运算符栈中弹出一个运算符,再从操作数栈中弹出所需的操作数,并且将运算结果压入操作数栈中

算法过程图示

这里写图片描述
(这个是《算法 第四版》里面的算法轨迹图,感觉很生动形象)

代码实现(这里是用java)

public class MyDijkstraAlgorithm {
    public static void main(String[] args) {
        dijkstraAlgorithm("(1+((2+3)*(4*5)))");
    }

    public static void dijkstraAlgorithm (String str) {

        //创建操作符栈
        Stack<Character> ops = new Stack<>();
        //创建操作数栈
        Stack<Double> nums = new Stack<>();
        for (int i = 0 ; i < str.length(); i++) {
            char s = str.charAt(i);
            switch (s) {
                //无视左括号
                case '(':
                    break;
                // + 、 - 、 * 、/、sqrt 这些操作符都压入栈
                case '+':
                    ops.push(s);
                    break;
                case '-':
                    ops.push(s);
                    break;
                case '*':
                    ops.push(s);
                    break;
                case '/':
                    ops.push(s);
                    break;
                case ')':
                    //遇到右括号时,根据从操作符栈中取出操作符,并从操作数栈中取出相应都操作数进行计算,并将计算结果压入操作数栈
                    char op = ops.pop();
                    Double num = nums.pop();
                    switch (op) {
                        case '+':
                            num = num + nums.pop();
                            break;
                        case '-':
                            num = num - nums.pop();
                            break;
                        case '*':
                            num = num * nums.pop();
                            break;
                        case '/':
                            num = num / nums.pop();
                            break;
                    }
                    nums.push(num);
                    break;
                default:
                    nums.push(Double.parseDouble(Character.toString(s)));
                    break;
            }
        }
        System.out.println(nums.pop());
    }
}

最后说两句

这个算法虽然看起来实用性不大,但是它充分利用了栈的特性,执行效率也比较高,我可以学习它的思路,把一些比较复杂的问题给简化了;


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值