利用棧和佇列計算帶有括號的表示式(純理論)
可以使用將中綴表示式轉為字尾的方法。
在這裡我以一個例子來說明:先將9+(3-1)*3+10/2轉為字尾表示式9 3 1 - 3 * + 10 2 / +,再通過計算字尾表示式得到20這個結果。
在這裡簡單的介紹一下轉換原則:
1.當讀到一個運算元時,立即將它放到輸出中。操作符則不立即輸出,放入棧中。遇到左圓括號也推入棧中。
2.如果遇到一個右括號,那麼就將棧元素彈出,將符號寫出直到遇到一個對應的左括號。但是這個左括號只被彈出,並不輸出。
3.在讀到操作符時,如果此時棧頂操作符優先性大於或等於此操作符,彈出棧頂操作符直到發現優先順序更低的元素位置。除了處理)的時候,否則決不從棧中移走”(”。操作符中,+-優先順序最低,()優先順序最高。
4.如果讀到輸入的末尾,將棧元素彈出直到該棧變成空棧,將符號寫到輸出中。
我們將在這個簡單的例子中實踐以上四條原則。
表示式為:9+(3-1)*3+10/2.
先讀入9,送到輸出,再讀入+,此時狀態如下:
輸出: 9
棧: +
然後讀入(、3、-、1,可以得到:
輸出: 9 3 1
棧: + ( -
接著讀入),根據原則三,將-和(彈出,(不輸出:
輸出: 9 3 1 -
棧: +
讀入*,因為*優先順序比+高,所以不彈出+:
輸出: 9 3 1 -
棧: + *
讀入3和+,因為+優先順序最低,依次彈出*、+,並把+入棧:
輸出: 9 3 1 - 3 * +
棧: +
讀入10、/,狀態為:
輸出: 9 3 1 - 3 * + 10
棧: + /
再讀入2,輸入為空,按原則四彈出棧中所有元素:
輸出:9 3 1 - 3 * + 10 2 / +
這樣把中綴表示式轉為字尾就完成了,可以進行下一步了。
- 思考題:如何把a+b*c+(d*e+f)*g轉為字尾表示式?
我會在本文結尾把答案公佈。
接下來,我們要計算剛剛得到的字尾表示式。讓我們把輸出看成一個先進先出佇列,通過棧存放所有結果,然後進行計算。
現在佇列為:9 3 1 - 3 * + 10 2 / +,棧為空。
將9、3、1放入棧中,得到:
佇列:- 3 * + 10 2 / +
棧:9 3 1
再讀入 - ,這時從棧中彈出兩個元素進行運算,即3-1,得到2,再壓棧儲存:
佇列:3 * + 10 2 / +
棧:9 2
按順序繼續進行,將3放入:
佇列:* + 10 2 / +
棧:9 2 3
讀入*,計算2*3,儲存6:
佇列:+ 10 2 / +
棧:9 6
接下來只要依次進行就好了:
佇列:10 2 / +
棧:15
佇列:/ +
棧:15 10 2
佇列:+
棧:15 5
佇列為空
棧:20
這樣運算就結束了,得到了正確結果20。
中綴轉字尾的答案為:a b c * + d e * f + g * +,如果你答對了,恭喜你;如果沒有答對,請再看一遍那四條原則,思考一下到底是哪裡錯了?