利用基於棧結構的逆波蘭表示式實現四則運算

2021-10-01 15:08:38 字數 3908 閱讀 8206

棧是一種操作受限的線性表,即只允許從一端插入和刪除資料,他的儲存方式分為線性儲存和鏈結儲存。棧的乙個最重要的特徵就是棧的插入和刪除只能在棧頂進行,所以每次刪除的元素都是最後進棧的元素,故棧也被稱為後進先出(lifo)表。棧主要有兩種操作,分為入棧(push)和出棧(pop)。由於只操作棧頂元素,所以此操作的複雜度為o(1)。

逆波蘭表示式又叫做字尾表示式。逆波蘭表示法是波蘭邏輯學家j・盧卡西維茲(j・ lukasewicz)於2023年首先提出的一種表示式的表示方法後來,人們就把用這種表示法寫出的表示式稱作「逆波蘭表示式」。逆波蘭表示式把運算量寫在前面,把算符寫在後面。逆波蘭表示式是一種十分有用的表示式,它將複雜表示式轉換為可以依靠簡單的操作得到計算結果的表示式。例如(a+b)*(c+d)轉換為ab+cd+*。如果當前字元為變數或者為數字,則壓棧,如果是運算子,則將棧頂兩個元素彈出作相應運算,結果再入棧,最後當表示式掃瞄完後,棧裡的就是結果。

本篇文章重點是說明四則運算轉換成逆波蘭表示式,最後計算表示式結果,所以本次只考慮四則運算。接下來,我們會以乙個例子講解運算過程。

四則運算表示式:

3 + 4 * (5 + 6 / 7) / (8 - 9) - 10 + 11
從左到右遍歷中綴表示式的每個數字和符號,若是數字則直接輸出,若是符號,則判斷其於棧頂符號的優先順序,是有括號或者優先順序低於棧頂符號,則棧頂元素依次出棧並輸出,直到遇到左括號或棧空才將之前那個符號入棧。

為說明方便簡單,這裡設定逆波蘭表示式為exp,符號棧為stack。以下每一步驟處理乙個字元。

01)"3"為數字,所以輸出3。此時exp為{3};stack為{}。

02)"+"為符號,並且棧頂為空,所以壓入棧頂。此時exp為{3};stack為{+}。

03)"4"為數字,所以輸出4。此時exp為{3 4} ;stack為{+}。

04)"*"為符號,此時棧頂元素為"+",並且優先順序小於"*",所以"*"壓人棧頂。此時exp為{3 4},stack為{+ *}。

05)"("為符號,並且為左括號,所以"("壓人棧頂。此時exp為{3 4},stack為{+ * (}。

06)"5"為數字,所以輸出5。此時exp為{3 4 5} ;stack為{+ * (}。

07)"+"為符號,此時棧頂元素為"(",所以"+"壓人棧頂。此時exp為{3 4 5 },stack為{+ * ( +}。

08)"6"為數字,所以輸出6。此時exp為{3 4 5 6} ;stack為{+ * ( +}。

09)"/"為符號,此時棧頂元素為+,優先順序低於"/",所以"/"壓入棧頂。此時exp為{3 4 5 6} ;stack為{+ * ( + /}。

10) "7"為數字,所以輸出7。此時exp為{3 4 5 6 7} ;stack為{+ * ( + /}。

11)")"為符號,並且為右括號。所以依次將棧內左括號"("以前的運算符號依次彈出。此時exp為{3 4 5 6 7 / +};stack為{+ *}。

12)"/"為運算符號,此時棧頂元素為"*",優先順序等於"/",所以彈出棧頂元素"*;接下來,此時棧頂元素為"+",優先順序低於"/",所以壓入棧頂。此時exp為{3 4 5 6 7 / + *};stack為{+ /}。

13)"("為符號並且為左括號,所以壓入棧頂。此時exp為{3 4 5 6 7 / + *};stack為{+ / (}。

14)"8"為數字,所以輸出8。此時exp為{3 4 5 6 7 / + * 8};stack為{+ / (}。

15)"-"為符號,棧頂元素為"(",所以直接壓入棧頂。此時exp為{3 4 5 6 7 / + * 8};stack為{+ / ( -}。

16)"9"為數字,所以輸出9。此時exp為{3 4 5 6 7 / + * 8 9};stack為{+ / ( -}。

17)")"為符號且為有括號,將棧中左括號以前的運算子彈出棧。此時exp為{3 4 5 6 7 / + * 8 9 -};stack為{+ / }。

18)"-"為運算符號,此時棧頂元素為"/",優先順序大於"-",所以彈出棧頂元素"/";此時棧頂元素為"+",優先順序等於"-",所以彈出棧頂元素"+",同時將"-"壓如棧頂。此時exp為{3 4 5 6 7 / + * 8 9 - / +};stack為{- }。

19)"10"為數字,所以輸出10。此時exp為{3 4 5 6 7 / + * 8 9 - / + 10};stack為{- }。

20)"+"為運算符號,此時棧頂元素為"-",優先順序等於"+",所以彈出棧頂元素,同時將"+"壓如棧頂。此時exp為{3 4 5 6 7 / + * 8 9 - / + 10 -};stack為{+ }。

21)"11"為數字,所以輸出11。此時exp為{3 4 5 6 7 / + * 8 9 - / + 10 - 11};stack為{+ }。

22)將棧內元素依次彈出。所以最終的exp為{3 4 5 6 7 / + * 8 9 - / + 10 - 11 + }。

遍歷逆波蘭表示式的每個元素,如果為數字,則壓入棧頂;如果是符號,則彈出棧頂兩個元素,將資料進行運算,得到的資料壓入棧頂。

通過上面計算的表示式為{3 4 5 6 7 / + * 8 9 - / + 10 - 11 + }。

為說明方便簡單,這裡涉及到乙個棧,我們定義為stack.

1)3為數字,壓入棧頂。此時stack為{3}。

2)4為數字,壓入棧頂。此時stack為{3 4}。

3)5為數字,壓入棧頂。此時stack為{3 4 5}。

4)6為數字,壓入棧頂。此時stack為{3 4 5 6}。

5)7為數字,壓入棧頂。此時stack為{3 4 5 6 7}。

6)"/"為符號,此時彈出棧頂兩個元素為6和7,所以將6和7做"/"運算,得到資料為0.857。並將0.857壓入棧頂。

此時stack為{3 4 5 0.857}。

7)"+"為符號,此時彈出棧頂兩個元素為5和0.857,所以將5和0.857做"+"運算,得到資料為5.857。並將5.857壓入棧頂。

此時stack為{3 4 5.857}。

8)"*"為符號,此時彈出棧頂兩個元素為4和5.857,所以將4和5.857做"*"運算,得到資料為23.428。並將23.428壓入棧頂。

此時stack為{3 23.428}。

9)8為數字,壓入棧頂。此時stack為{3 23.428 8}。

9)9為數字,壓入棧頂。此時stack為{3 23.428 8 9}。

10)"-"為符號,此時彈出棧頂兩個元素為8和9,所以將8和9做"-"運算,得到資料為-1。並將-1壓入棧頂。

此時stack為{3 23.428 -1}。

11)"/"為符號,此時彈出棧頂兩個元素為23.428和-1,所以將23.428和-1做"/"運算,得到資料為-23.428。並將-23.428壓入棧頂。

此時stack為{3 -23.428}。

11)"+"為符號,此時彈出棧頂兩個元素為3和 -23.428,所以將3和 -23.428做"+"運算,得到資料為-20.428。並將-20.428壓入棧頂。

此時stack為{-20.428}。

12)"10"為數字,壓入棧頂。此時stack為{-20.428 10}。

13)"-"為符號,此時彈出棧頂兩個元素為-20.428和10,所以將-20.428和10做"-"運算,得到資料為-30.428。並將-30.428壓入棧頂。

此時stack為{-30.428}。

14)"11"為數字,壓入棧頂。此時stack為{-30.428 11}。

15)"+"為符號,此時彈出棧頂兩個元素為-30.428和11,所以將-30.428和11做"+"運算,得到資料為-19.428。並將-19.428壓入棧頂。

此時stack為{-19.428}。

16)逆波蘭表示式遍歷完畢,此時棧頂的資料即為計算的結果。為-19.428。

17)我們通過計算器計算得到的結果為:-19.429

波蘭表示式和逆波蘭表示式(棧)

中綴表示式如1 2 2 1 其運算子一般出現在運算元之間,因此稱為中綴表示式,也就是大家程式設計中寫的表達 式。編譯系統不考慮表示式的優先級別,只是對表示式從左到右進行掃瞄,當遇到運算子時,就把其前面的兩 個運算元取出,進行操作。為達到上述目的,就要將中綴表示式進行改寫,變為字尾表示式 如上面的表示...

波蘭表示式 逆波蘭表示式

中綴表示式是最常見的運算表示式,如 3 5 2 6 1 波蘭表示式又稱為字首表示式,它是由中綴表示式經過一定的方式轉換來的 比如中綴表示式為 3 5x 2 6 1 對應的字首表示式為 3 x 5 2 6 1 對於中綴表示式從右向左遍歷轉換為字首表示式,中途要是用棧進行儲存 轉換規則如下 波蘭表示式 ...

棧和逆波蘭表示式

1 2,1 3 2,1 3 2 1 3 這些就是中綴表示式,就是我們 平時經常見到的形式,先算加減再算乘除,有括號的先算括號裡面的,沒有括號按照優先順序順序進行計算。但是,計算機處理中綴表示式卻並不方便,因為沒有一種簡單的資料結構可以方便從乙個表示式中間抽出,一部分算完結果,再放進去,然後繼續後面的...