1 前言
逆波蘭表示法(Reverse Polish notation,RPN,或逆波蘭記法),是一種是由波蘭數學家揚·武卡謝維奇1920年引入的數學表達式方式,在逆波蘭記法中,所有操作符置於操作數的后面,因此也被稱為后綴表示法。逆波蘭記法不需要括號來標識操作符的優先級。
2 表達式
2.1 中綴表達式
2.1.1 定義
中綴表達式就是我們最熟悉的一種表達式:1+2,3(3+4),1+23+6,...等都是中綴表示法。對於人們來說,也是最直觀的一種求值方式,先算括號里的,
然后算乘除,最后算加減,但是,計算機處理中綴表達式卻並不方便,故引出了前綴和后綴。中綴表達式得名於它是由相應的語法樹的中序遍歷的結果得到的。
2.2 前綴表達式
2.2.1 定義
前綴表達式又叫做波蘭式。同樣的道理,表達式的前綴表達式是由相應的語法樹的前序遍歷的結果得到的。
如1 + 2 * (3 - 4) - 5 * 6
的前綴表達式為- + 1 * 2 - 3 4 * 5 6
2.2.2 求值
由前綴表達式求出結果有下面兩種思路:
- 從左至右掃描表達式,如果一個操作符后面跟着兩個操作數時,則計算。然后將結果作為操作數替換(這個操作符和兩個操作數), 重復此步驟,直至所有操作符處理完畢。如
- + 1 * 2 - 3 4 * 4 5
,掃描到- 3 4
時,會計算3 - 4 = -1
,表達式變成:- + 1 * 2 -1 * 5 6
繼續掃描到* 2 -1
,計算2 * -1 = -2
,表達式變成:- + 1 -2 * 5 6
,繼續+ 1 -2
,依此類推。 - 由1知,要多遍掃描表達式,比較復雜,我們可以用一個棧S來實現計算,掃描從右往左進行,如果掃描到操作數,則壓進S,如果掃描到操作符,則從S彈出兩個操作數進行相應的操作,並將結果壓進S(S出2進1),當掃描結束后,S的棧頂就是表達式結果。
2.3 后綴表達式
2.3.1 定義
后綴表達式又叫做逆波蘭式。它是由相應的語法樹的后序遍歷的結果得到的。如1 + 2 * (3 - 4) - 5 * 6
的后綴表達式為:1 2 3 4 - * + 5 6 * -
注意:逆波蘭記法並不是簡單的波蘭表達式的反轉。因為對於不滿足交換律的操作符,它的操作數寫法仍然是常規順序,如,波蘭記法“/ 6 3”的逆波蘭記法是“6 3 /”而不是“3 6 /”;數字的數位寫法也是常規順序。
2.3.2 求值
由前綴表達式求出結果十分方便,只需要用一個棧S實現:
- 掃描從左往右進行,如果掃描到操作數,則壓進S,如果掃描到操作符,則從S彈出兩個操作數進行相應的操作,並將結果壓進S(S出2進1),當掃描結束后,S的棧頂就是表達式結果。
- 后綴表達式和前綴表達式看起來就像一對逆過程,實際上並不是這樣子,因為字符讀取的時候都是從左往右的,所以,前綴表達式往往需要用兩個棧來計算,其中一個棧用來預處理:將字符串倒序壓進棧中。
3 表達式轉換
3.1 中綴表達式轉換成后綴表達式
既然中綴表達式對於計算機的運算並不便利,而前綴后綴表達式的計算相對簡單方便。因此,找到一種途徑將中綴表達式轉換成前綴后綴表達式就十分重要。實際上,二者的轉換算法看起來也很像一個逆過程。因此,我們着重討論中綴轉后綴。
從理論上講,已知一棵二叉樹的中序遍歷序列,要求出它的后序遍歷序列是不唯一的,即文法是有多義性的。所以,在這里我們要加上優先級這一限制條件,轉換就變得唯一了。
3.1.1 算法
- 算法: 中綴表達式轉換成后綴表達式.
- 輸入: 中綴表達式串.
- 輸出: 后綴表達式串.
PROCESS BEGIN:
1.從左往右掃描中綴表達式串s,對於每一個操作數或操作符,執行以下操作;
2.IF (掃描到的s[i]是操作數DATA)
將s[i]添加到輸出串中;
3.IF (掃描到的s[i]是開括號'(')
將s[i]壓棧;
4.WHILE (掃描到的s[i]是操作符OP)
IF (棧為空 或 棧頂為'(' 或 掃描到的操作符優先級比棧頂操作符高)
將s[i]壓棧;
BREAK;
ELSE
出棧至輸出串中
5.IF (掃描到的s[i]是閉括號')')
棧中運算符逐個出棧並輸出,直到遇到開括號'(';
開括號'('出棧並丟棄;
6.返回第1步
7.WHILE (掃描結束而棧中還有操作符)
操作符出棧並加到輸出串中
PROCESS END
3.1.2 例子
中綴表達式5 + ((1 + 2) * 4) - 3
寫作轉換成后綴表達式:5 1 2 + 4 * + 3 -
下表給出了該逆波蘭表達式從左至右求值的過程,堆棧欄給出了中間值,用於跟蹤算法。
輸入 | 操作 | 堆棧 | 注釋 |
---|---|---|---|
5 | 入棧 | 5 | |
1 | 入棧 | 5, 1 | |
2 | 入棧 | 5, 1, 2 | |
+ | 加法運算 | 5, 3 | 1, 2出棧,將結果3入棧 |
4 | 入棧 | 5, 3, 4 | |
* | 乘法運算 | 5, 12 | 3, 4出棧,將結果12入棧 |
+ | 加法運算 | 17 | 5, 12出棧,將結果17入棧 |
3 | 入棧 | 17, 3 | |
- | 減法運算 | 14 | 17, 3出棧,將結果14入棧 |
計算完成時,棧內只有一個操作數,這就是表達式的結果:14
。
上述運算可以重寫為如下運算鏈方法:1 2 + 4 * 5 + 3 -
3.2 中綴表達式轉換成前綴表達式
中綴表達式轉換成前綴表達式和中綴表達式轉換成后綴表達式十分類似,只需要將掃描方向由前往后變成由后往前,將(
改為)
,)
改為(
。
4 END
具體的應用可以見我的另外一篇博客:基於逆波蘭表達式實現圖形化混合計算器.