中綴表達式就是我們日常用的算術表達式。
前綴表達式是將運算符放在兩個操作數之前。後綴表達式(又稱逆波蘭表達式)是將運算符放在兩個操作數之後。例如:中綴表達式(A+(B-C/D)*E)對應的前綴表達式是(+A*-B/CDE)對應的後綴表達式爲(ABCD/-E*+)
說到轉化之前我們先來看一下符號的優先級問題。
運算符 | (左括號 | +加,-減 | *乘,/除,%取模 | ^冪 |
優先級 | 0 | 1 | 2 | 3 |
下面我們來弄清兩個問題。
爲什麼我們要把中綴表達式轉化爲後綴表達式去計算?怎樣將中綴表達式轉化爲後綴表達式?
第一個問題,只要提到計算器的實現,基本上都會想到使用後綴表達式來實現,後綴表達式計算機操作起來方便(例如a+b*c,計算器從左向右掃描,假設已經掃描到b那個位置了,計算器怎樣知道要不要現在就計算a+b呢?是的,可以用一個判斷語句來判斷甚至用一個更牛的語句來判斷是否立刻就要計算a+b,但是我就問你一句,你不嫌麻煩嗎?後綴表達式就不一樣,就很牛了,只要壓入的符合後綴表達式的條件計算器就去計算吧,絕對正確。當然了,從下面給出的規則來看,後綴表達式開出的條件並不算太麻煩。何樂而不用呢?)加加減減是按照後綴表達式的順序來的,計算機一直對棧頂元素進行操作就行了。很方便。如果你有其他的實現方法,歡迎留言。
第二個問題,怎樣實現中綴表達式轉化爲後綴表達式?
1.初始化一個棧,棧中元素是char類型,因爲是要用這個棧來儲存運算符的。
2.從算數表達式輸入的字符串中依次從左向右每次讀取一個字符。
3.如果當前字符是操作數,則直接填寫到後綴表達式。
4.如果當前字符是(左括號,將其壓入運算符棧。
5.如果當前字符爲運算符,則
5.1.當運算符棧爲空,則將其壓入運算符棧。
5.2.當此運算符的優先級高於棧頂元素的時候,則將此運算符壓入運算符棧;否則,彈出棧頂運算符到後綴表達式,並且將當前運算符壓棧。回到步驟2.
6.如果當前字符是)右括號,反覆將棧頂元素彈出到後綴表達式,直到棧頂元素是左括號(爲止,並將左括號從棧中彈出丟棄。
7.如果讀取還未完成,回到步驟2.
8.如果讀取完成,則將棧中剩餘的運算符依次彈出到後綴表達式。
我們再來看看後綴表達式怎樣求值的:
從左至右掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(次頂元素 op 棧頂元素),並將結果入棧;重複上述過程直到表達式最右端,最後運算得出的值即爲表達式的結果。
例如後綴表達式“3 4 + 5 × 6 -”:
(1) 從左至右掃描,將3和4壓入堆棧;
(2) 遇到+運算符,因此彈出4和3(4爲棧頂元素,3爲次頂元素,注意與前綴表達式做比較),計算出3+4的值,得7,再將7入棧;
(3) 將5入棧;
(4) 接下來是×運算符,因此彈出5和7,計算出7×5=35,將35入棧;
(5) 將6入棧;
(6) 最後是-運算符,計算出35-6的值,即29,由此得出最終結果。
前綴的轉換和後綴的轉換的比較:
|
中綴轉前綴 |
中綴轉後綴 |
棧 |
操作符棧 |
操作符棧 |
掃描順序 |
從右到左 |
從左到右 |
遇到操作數 |
直接歸入 |
直接歸入 |
遇到右括號 |
直接入棧 |
將棧中操作符依次彈棧,歸入,直至遇到左括號,將左括號彈棧,處理完畢 |
遇到左括號 |
將棧中操作符依次彈棧,歸入,直至遇到右括號,將右括號彈棧,處理完畢 |
直接入棧 |
遇到其他操作符 |
檢測棧頂操作符優先級與當前操作符優先級關係,如果棧頂大於當前,則出棧,歸入,直至棧頂小於等於當前,並將當前操作符入棧 |
檢測棧頂與當前優先級關係,如果棧頂大於等於當前則出棧,歸入,直至棧頂小於當前,並將當前操作符入棧 |
操作符棧中的優先級 |
從棧底到棧頂操作優先級:非遞減。即:棧頂可以大於或等於下面的 |
從棧底到棧頂優先級:遞增。即:棧頂必須大於下面的 |
是否翻轉 |
翻轉 |
無需翻轉 |
中綴表達式怎樣轉化爲前綴表達式?
1.初始化運算符棧。
2.從算數表達式輸入的字符串中依次從右向左每次讀取一個字符。
3.如果當前字符是操作數,直接填寫到前綴表達式。
4.如果當前字符是)右括號,將其壓入運算符棧。
5.如果當前字符爲運算符,則
5.1.當運算符棧爲空,則將其壓入運算符棧。
5.2.當此運算符的優先級高於或等於棧頂元素的時候,則將此運算符壓入運算符棧;否則,彈出棧頂運算符到前綴表達式,並且將當前運算符壓棧。回到步驟2.
6.如果當前字符是(左括號,反覆將棧頂元素彈出到前綴表達式,直到棧頂元素是右括號)爲止,並將右括號從棧中彈出丟棄。
7.如果讀取還未完成,回到步驟2.
8.如果讀取完成,則將棧中剩餘的運算符依次彈出到前綴表達式。
9.翻轉
例如,將中綴表達式“(2+3)×4”轉換爲前綴表達式的過程如下:
掃描元素 | 棧底---棧頂 | 解釋說明 | 前綴表達式 |
4 | NULL | 數字直接加入前綴表達式 | 4 |
* | * | 運算符棧爲空,則將其壓入運算符棧(5.1) | 4 |
) | ) | )的優先級小於*,所以將 * 彈出並將 | 4* |
3 | ) | 數字直接加入前綴表達式 | 4*3 |
+ | )+ | + 的優先級),將 + 壓入運算符棧 | 4*3 |
2 | )+ | 數字直接加入前綴表達式 | 4*32 |
( | NULL | 反覆將棧頂元素彈出到前綴表達式,直到棧頂元素是右括號)爲止,並將右括號從棧中彈出丟棄 | 4*32+ |
因此,前綴表達式爲: + 2 3 * 4;