1. 程式人生 > >棧的簡單應用——中綴表示式與字尾表示式

棧的簡單應用——中綴表示式與字尾表示式

中綴表示式:(1+((2+3)*(4*5)))

E.W.Dijkstra雙棧演算法

1.將運算元壓入運算元棧。

2.將運算子壓入運算子棧。

3.忽略左括號。

4.在遇到右括號時,彈出一個運算子,彈出所需數量的操縱數,並將運算子和運算元的運算結果壓入運算元棧。

public static void main(String[] args) {
            Stack<String> ops  = new Stack<String>();
            Stack<Double> vals = new Stack<Double>();

            while(!StdIn.isEmpty()) {
                String s=StdIn.readString();
                if      (s.equals("("))               ;
                else if (s.equals("+"))    ops.push(s);
                else if (s.equals("-"))    ops.push(s);
                else if (s.equals("*"))    ops.push(s);
                else if (s.equals("/"))    ops.push(s);
                else if (s.equals("sqrt")) ops.push(s);
                else if (s.equals(")")) {
                    String op = ops.pop();
                    double v = vals.pop();
                    if      (op.equals("+"))    v = vals.pop() + v;
                    else if (op.equals("-"))    v = vals.pop() - v;
                    else if (op.equals("*"))    v = vals.pop() * v;
                    else if (op.equals("/"))    v = vals.pop() / v;
                    else if (op.equals("sqrt")) v = Math.sqrt(v);
                    vals.push(v);
                }
                else vals.push(Double.parseDouble(s));
            }
            StdOut.println(vals.pop());
        }

演算法是程式碼參考Robert Sedgewick的Algorithms 4th Edition下壓棧部分,之後想著用他給出的Stack類來實現字尾表示式。

字尾表示式:1 3 2 - 4 5 * * +

字尾表示式是兩個運算元後面加一運算子,上面表示式即 1 ( (3 2 -)(4 5 *) *) +

此時的思路並非仍是建立雙棧來壓入和彈出進行運算,而是壓入運算元後一碰到後面緊跟運算子直接進行運算,再壓入運算元棧,但是要注意的是彈出運算元時運算先彈出的是減數或除數(加和乘便不用考慮彈出順序)。

public static void main(String[] args) {
        Stack<Double> vals = new Stack<Double>();
        double v=0;
        while(!StdIn.isEmpty()) {
            String s=StdIn.readString();
            
            if (s.equals("+")) {double right=vals.pop();
            double left=vals.pop();v=left+right; vals.push(v);}
            else if (s.equals("-")) {double right=vals.pop();
            double left=vals.pop();v=left-right; vals.push(v);}  
            else if (s.equals("*")) {double right=vals.pop();
            double left=vals.pop();v=left*right; vals.push(v);}
            else if (s.equals("/")) {double right=vals.pop();
            double left=vals.pop();v=left/right; vals.push(v);}
            else vals.push(Double.parseDouble(s));
        }

        StdOut.println(vals.pop());
    }

每次彈出兩個時還要分別賦值真的很心累。之後深入學習後再來嘗試想想別的方法,還有關於中綴表示式與字尾表示式的轉化問題。不得不說E.W.Dijkstra的雙棧演算法真的很妙,值得反覆學習。