什麼是字尾表示式(逆波蘭式)
不包含括號,運算子放在兩個運算物件的後面,所有的計算按運算子出現的順序,嚴格從左向右進行(不再考慮運算子的優先規則,
如:(2 + 1) * 3 , 即2 1 + 3 *
中綴表示式
(或中綴記法)是乙個通用的算術或邏輯公式表示方法, 操作符是以中綴形式處於運算元的中間(例:3 + 4),中綴表示式是人們常用的算術表示方法。
與字首表示式(例:+ 3 4)或字尾表示式(例:3 4 +)相比,中綴表示式不容易被計算機解析,但仍被許多程式語言使用,因為它符合人們的普遍用法。
與字首或字尾記法不同的是,中綴記法中括號是必需的。計算過程中必須用括號將操作符和對應的運算元括起來,用於指示運算的次序。
例: (1)8+4-6*2用字尾表示式表示為:
8 4+6 2*-
(2)2*(3+5)+7/1-4用字尾表示式表示為:
35+2*71/4-+
含義:字首表示式的運算子位於運算元之前。
字首表示式的計算機求值:
從右至左掃瞄表示式,遇到數字時,將數字壓入堆疊,遇到運算子時,彈出棧頂的兩個數,用運算子對它們做相應的計算(棧頂元素 op 次頂元素),並將結果入棧;重複上述過程直到表示式最左端,最後運算得出的值即為表示式的結果。
例如字首表示式「- × + 3 4 5 6」:
(1) 從右至左掃瞄,將6、5、4、3壓入堆疊;
(2) 遇到+運算子,因此彈出3和4(3為棧頂元素,4為次頂元素,注意與字尾表示式做比較),計算出3+4的值,得7,再將7入棧;
(3) 接下來是×運算子,因此彈出7和5,計算出7×5=35,將35入棧;
(4) 最後是-運算子,計算出35-6的值,即29,由此得出最終結果。
可以看出,用計算機計算字首表示式的值是很容易的。
將中綴表示式轉換為字首表示式:
遵循以下步驟:
(1) 初始化兩個棧:運算子棧s1和儲存中間結果的棧s2;
(2) 從右至左掃瞄中綴表示式;
(3) 遇到運算元時,將其壓入s2;
(4) 遇到運算子時,比較其與s1棧頂運算子的優先順序:
(4-1) 如果s1為空,或棧頂運算子為右括號「)」,則直接將此運算子入棧;
(4-2) 否則,若優先順序比棧頂運算子的較高或相等,也將運算子壓入s1;
(4-3) 否則,將s1棧頂的運算子彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算子相比較;
(5) 遇到括號時:
(5-1) 如果是右括號「)」,則直接壓入s1;
(5-2) 如果是左括號「(」,則依次彈出s1棧頂的運算子,並壓入s2,直到遇到右括號為止,此時將這一對括號丟棄;
(6) 重複步驟(2)至(5),直到表示式的最左邊;
(7) 將s1中剩餘的運算子依次彈出並壓入s2;
(8) 依次彈出s2中的元素並輸出,結果即為中綴表示式對應的字首表示式。
例如,將中綴表示式「1+((2+3)×4)-5」轉換為字首表示式的過程如下:
掃瞄到的元素
s2(棧底->棧頂)
s1(棧底->棧頂)說明5
5空數字,直接入棧-5
-s1為空,運算子直接入棧)5
-)右括號直接入棧454
-)數字直接入棧x54
-)xs1棧頂是右括號,直接入棧)54
-)x)
右括號直接入棧
3543
-)x)
數字直接入棧
+543
-)x)+
s1棧頂是右括號直接入棧
25432
-)x)+
數字直接入棧
(5432+
-)x左括號,彈出運算子+至s2,直至遇到右括號一對括號丟棄
(5432+x
-左括號,彈出運算子x,直至遇到右括號,一對括號丟棄
+5432+x
-+優先順序相同,入棧
15432+x1
-+數字直接入棧
到達最左端
54321+x1+-
空s1中剩餘的依次彈出並壓入s2
因此結果為「- + 1 × + 2 3 4 5」。
中綴表示式轉字尾表示式
與轉換為字首表示式相似,遵循以下步驟:
(1) 初始化兩個棧:運算子棧s1和儲存中間結果的棧s2;
(2) 從左至右掃瞄中綴表示式;
(3) 遇到運算元時,將其壓入s2;
(4) 遇到運算子時,比較其與s1棧頂運算子的優先順序:
(4-1) 如果s1為空,或棧頂運算子為左括號「(」,則直接將此運算子入棧;
(4-2) 否則,若優先順序比棧頂運算子的高,也將運算子壓入s1(注意轉換為字首表示式時是優先順序較高或相同,而這裡則不包括相同的情況);
(4-3) 否則,將s1棧頂的運算子彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算子相比較;
(5) 遇到括號時:
(5-1) 如果是左括號「(」,則直接壓入s1;
(5-2) 如果是右括號「)」,則依次彈出s1棧頂的運算子,並壓入s2,直到遇到左括號為止,此時將這一對括號丟棄;
(6) 重複步驟(2)至(5),直到表示式的最右邊;
(7) 將s1中剩餘的運算子依次彈出並壓入s2;
(8) 依次彈出s2中的元素並輸出,結果的逆序即為中綴表示式對應的字尾表示式**換為字首表示式時不用逆序)。
例如,將中綴表示式「1+((2+3)×4)-5」轉換為字尾表示式的過程如下:
掃瞄到的元素
s2(棧底->棧頂)
s1(棧底->棧頂)說明1
1空數字直接入棧+1
+運算子直接入棧頂(1
+(左括號直接入棧(1
+((左括號直接入棧212
+((數字直接入棧+12
+((+
s1棧頂為左括號,直接入棧
3123
+((+
數字直接入棧
)123+
+(右括號,彈出運算子至s2直至遇到左括號
x123+
+(xs1棧頂為左括號,直接入棧
4123+4
+(x數字直接入棧
)123+4x
+右括號,彈出運算子x,去掉括號
-123+4x+
-同級運算子,壓入棧
5123+4x+5
-數字直接入棧
到達最後
123+4x+5-空空
因此結果為「1 2 3 + 4 × + 5 -」(注意需要逆序輸出)。
字尾表示式的求值
將中綴表示式轉換成等價的字尾表示式後,求值時,不需要再考慮運算子的優先順序,只需從左到右掃瞄一遍字尾表示式即可。具體求值步驟為:從左到右掃瞄字尾表 達式,遇到運算子就把表示式中該運算子前面兩個運算元取出並運算,然後把結果帶回字尾表示式;繼續掃瞄直到字尾表示式最後乙個表示式。
例如,字尾表示式(abc*+def*/-) 的求值
字尾表示式的求值的演算法
設定乙個棧,開始時,棧為空,然後從左到右掃瞄字尾表示式,若遇運算元,則進棧;若遇運算子,則從棧中退出兩個元素,先退出的放到運算子的右邊,後退出的 放到運算子左邊,運算後的結果再進棧,直到字尾表示式掃瞄完畢。此時,棧中僅有乙個元素,即為運算的結果。
例,求字尾表示式:1 2 + 8 2 - 7 4 - / * 的值,
棧的變化情如下:
步驟棧中元素說明1
11進棧212
2進棧3
遇+號退棧2和143
1+2=3結果3進棧538
8進棧6
3822進棧
7遇-號退棧2和8836
8-2=6結果6進棧
9367
7進棧10
3674
4進棧11
遇-號退棧4和7
12363
7-4=3結果3入棧
13遇/號退棧3和6
1432
6/3=2結果2進棧
15遇*號退棧2和3166
2*3=6結果6進棧176
掃瞄完畢,運算結束
從上可知,最後求得的字尾表示式之值為6 ,與用中綴表示式求得的結果一致,但字尾式求值要簡單得多。
五、中綴表示式變成等價的字尾表示式的演算法
將中綴表示式變成等價的字尾表示式,表示式中運算元次序不變,運算子次序發生變化,同時去掉了圓括號。轉換規則是:設立乙個棧,存放運算子,首先棧為空, 編譯程式從左到右掃瞄中綴表示式,若遇到運算元,直接輸出,並輸出乙個空格作為兩個運算元的分隔符;若遇到運算子,則必須與棧頂比較,運算子級別比棧頂級 別高則進棧,否則退出棧頂元素並輸出,然後輸出乙個空格作分隔符;若遇到左括號,進棧;若遇到右括號,則一直退棧輸出,直到退到左括號止。當棧變成空時, 輸出的結果即為字尾表示式。將中綴表示式(1+2)*((8-2)/(7-4)) 變成等價的字尾表示式。
現在用棧來實現該運算,棧的變化及輸出結果如下:
表示式前字尾表達形式
原文 表示式的三種形式 中綴表示式 運算子放在兩個運算物件中間,如 2 1 3 字尾表示式 不包含括號,運算子放在兩個運算物件的後面,所有的計算按運算子出現的順序,嚴格從左向右進行 不再考慮運算子的優先規則,如 2 1 3 字首表示式 同字尾表示式一樣,不包含括號,運算子放在兩個運算物件的前面,如 ...
表示式 前字尾表達形式
35,15,80,70,20,字尾表達方式 35 15 80 70 20 25 中綴表達方式 35,15,80,70,20 字首表達方式 人的思維方式很容易固定 正如習慣拉10進製。就對2,3,4,8,16等進製不知所措一樣 人們習慣的運算方式是中綴表示式。而碰到字首,字尾方式。迷茫 其實僅僅是一種...
表示式前字尾表達形式
35,15,80,70,20,字尾表達方式 35 15 80 70 20 25 中綴表達方式 35,15,80,70,20 字首表達方式 人的思維方式很容易固定 正如習慣拉10進製。就對2,3,4,8,16 等進製不知所措一樣 人們習慣的運算方式是中綴表示式。而碰到字首,字尾方式。迷茫 其實僅僅是一...