四則運算表達式
一種不需要括號的后綴表達法,我們把它稱為逆波蘭(Reverse Polish Notation , RPN)表示。它將復雜表達式轉換為可以依靠簡單的操作得到計算結果的表達式,解決了四則運算中括號改變運算符優先級的問題。
我們先來看看,對於"9+(3-1)×3+10÷2",如果要用后綴表示法應該是什么樣子:“9 3 1 - 3 * + 10 2 / +” ,這樣的表達式稱為后綴表達式,叫后綴的原因在於所有的符號都是在要運算數字的后面出現。
一.后綴表達式計算結果
為了解釋后綴表達式的好處,我們先來看看,計算機如何應用后綴表達式計算出最終的結果20的。
后綴表達式:9 3 1 - 3 * + 10 2 / +
規則:從左到右遍歷表達式的每個數字和符號,遇到是數字就進棧,遇到是符號,就將處於棧頂兩個數字出棧,進行運算,運算結果進棧,一直到最終獲得結果。
1.初始化一個空棧。此棧用來對要運算的數字進行使用。如圖1左圖所示。
2.后綴表達式中前三個都是數字,所以9、3、1進棧,如圖1右圖所示。
圖1
3.接下來是“-” , 所以將棧中的1出棧作為減數,3出棧作為被減數,並運算3-1得到2,再將2進棧,如圖2左圖所示。
4.接着是數字3進棧,如圖2右圖所示。
圖2
5.后面是“*” , 也就意味着棧中3和2出棧,2與3相乘,得到6,並將6進棧,如圖3左圖所示。
6.下面是“+” , 所以棧中6和9出棧,9與6相加,得到15,將15出棧,如圖3右圖所示。
圖3
7.接着是10與2兩數字進棧,如圖4左圖所示。
8.接下來是符號“/” , 因此,棧頂的2與10出棧,10與2相除,得到5,將5進棧,如圖4右圖所示。
圖4
9.最后一個是符號“+” , 所以將15與5出棧並相加,得到20,將20進棧,如圖5左圖所示。
10.結果是20出棧,棧變為空,如圖5右圖所示。
圖5
果然,后綴表達式可以很順利解決計算的問題。
二.中綴表達式轉后綴表達式
我們把平時所用的標准四則運算表達式,即“9+(3-1)×3+10÷2”叫做中綴表達式。因為所有的運算符號都在兩數字的中間。
中綴表達式 “9+(3-1)×3+10÷2” 轉化為后綴表達式 “9 3 1 - 3 * + 10 2 / +” 。
規則:從左到右遍歷中綴表達式的每個數字和符號,若是數字就輸出,即成為后綴表達式的一部分;若是符號,則判斷其與棧頂符號的優先級,是右括號或優先級低於棧頂符號(乘除優先加減)則棧頂元素依次出棧並輸出,並將當前符號進棧,一直到最終輸出后綴表達式為止。
1.初始化一空棧,用來對符號進出棧使用。如圖6左圖所示。
2.第一個字符是數字9,輸出9,后面是符號“+”,進棧。如圖6的右圖所示。
圖6
3.第三個字符時“(” , 依然是符號,因其只是左括號,還沒配對,故進棧。如圖7左圖所示。
4.第四個字符是數字3,輸出,總表達式為9 3,接着是“—”,進棧。如圖7右圖所示。
圖7
5.接下來是數字1,輸出,總表達式為9 3 1,后面是符號“)” , 此時,我們需要去匹配此前的“(” , 所以棧頂依次出棧,並輸出,直到“(”出棧為止。此時左括號上方只有“—” , 因此輸出“—”。總的輸出表達式為9 3 1 — 。如圖8左圖所示。
6.緊接着是符號“×” ,因為此時的棧頂符號為“+”號,優先級低於“×” ,因此不輸出,“*”進棧。接着是數字3,輸出,總的表達式為 9 3 1 — 3 。 如圖8右圖所示。
圖8
7.之后是符號“+” ,此時當前棧頂元素“*”比這個“+”的優先級高,因此棧中元素出棧並輸出(沒有比“+”號更低的優先級,所以全部出棧),總輸出表達式為9 3 1 — 3 * + 。然后將當前這個符號“+”進棧。也就是說,前6張圖的棧底的“+”是指中綴表達式中開頭的9后面那個“+” ,而圖9左圖中的棧底(也是棧頂)的“+”是指“9+(3-1)×3+”中的最后一個“+”。
8.緊接着數字10,輸出,總表達式變為9 3 1 — 3 * + 10 。 后是符號“÷” ,所以“/”進棧。如圖9右圖所示。
圖9
9.最后一個數字2,輸出,總的表達式為9 3 1 — 3 * + 10 2 。如圖10左圖所示。
10.因已經到最后,所以將棧中符號全部出棧並輸出。最終輸出的后綴表達式結果為 9 3 1 — 3 * + 10 2 / + 。如圖10右圖所示。
圖10
從剛才的推導中會發現,要想讓計算機具有處理我們通常的標准(中綴)表達式的能力,最重要的就是兩步:
- 將中綴表達式轉化為后綴表達式(棧用來進出運算的符號)。
- 將后綴表達式進行運算得出結果(棧用來進出運算的數字)。