一、手工方式
如果只是用於解題的話,這種方法是最快最准確的。但是它不適用於計算機。下面以a+b*c+(d*e+f)*g
為例子講以下人應該怎么把中綴表達式轉換成后綴表達式。
-
按先加減后乘除的原則給表達式加括號
結果:
((a+(b*c))+(((d*e)+f)*g))
-
由內到外把每個括號里的表達式換成后綴
最終結果:
abc*+de*f+g*+
這樣就得到了中綴表達式轉后綴表達式的最終結果。此法應付考試有神效。
二、棧的方式
計算機畢竟沒有人的思路,需要借助棧來實現從中綴表達式到后綴表達式的轉換。
這里明確一下使用棧轉換的算法思想
從左到右開始掃描中綴表達式 遇到數字, 直接輸出 遇到運算符 a.若為“(” 直接入棧 b.若為“)” 將符號棧中的元素依次出棧並輸出, 直到 “(“, “(“只出棧, 不輸出 c.若為其他符號, 將符號棧中的元素依次出棧並輸出, 直到遇到比當前符號優先級更低的符號或者”(“。 將當前符號入棧。 掃描完后, 將棧中剩余符號依次輸出
下面以a+b*c+(d*e+f)*g
為例子來講講計算機的轉換過程。下面在描述棧的情況是直接用文字描述了,由左到右為棧底到棧頂。空表示棧空
-
由左向右遍歷表達式,首先遇到a,直接將其輸出。
此時輸出為:
a
棧的情況為:空
-
繼續遍歷,遇到+,將其放入棧中。
此時輸出為:
a
棧的情況為:+
-
繼續遍歷,遇到b,直接將其輸出。
此時輸出為:
ab
棧的情況為:+
-
繼續遍歷,遇到*,因為*的優先級大於棧頂的+,所以將*放入棧內。
此時輸出為:
ab
棧的情況為:+*
-
繼續遍歷,遇到c,直接將其輸出。
此時輸出為:
abc
棧的情況為:+*
-
繼續遍歷,遇到+,因為+的優先級低於棧頂的*,故將*彈出;然后新的棧頂元素的+與這個+優先級相同,故也要彈出現在棧頂的+;然后棧空了,將現在這個+放入棧中。
此時輸出為:
abc*+
棧的情況為:+
-
繼續遍歷,遇到(,直接將其放入棧中,不遇到)不會將(彈出。
此時輸出為:
abc*+
棧的情況為:+(
-
繼續遍歷,遇到d,直接將其輸出。
此時輸出為:
abc*+d
棧的情況為:+(
-
繼續遍歷,遇到*,因為棧頂為(,不遇到)不將(彈出,故直接將*放入棧中。
此時輸出為:
abc*+d
棧的情況為:+(*
-
繼續遍歷,遇到e,直接將其輸出。
此時輸出為:
abc*+de
棧的情況為:+(*
-
繼續遍歷,遇到+,因為+比棧頂*的優先級低,故將*彈出;新的棧頂元素為(,不遇到)不彈出(,故將+放入棧中。
此時輸出為:
abc*+de*
棧的情況為:+(+
-
繼續遍歷,遇到f,直接將其輸出。
此時輸出為:
abc*+de*f
棧的情況為:+(+
-
繼續遍歷,遇到),直接將棧中元素依次彈出並輸出直到遇到(為止,注意:(彈出但不輸出。
此時輸出為:
abc*+de*f+
棧的情況為:+
-
繼續遍歷,遇到*,因為*的優先級大於棧頂元素+的優先級,故直接將*入棧。
此時輸出為:
abc*+de*f+
棧的情況為:+*
-
繼續遍歷,遇到g,直接將其輸出。
此時輸出為:
abc*+de*f+g
棧的情況為:+*
-
繼續遍歷,為空,遍歷結束。將棧內元素依次彈出。
此時輸出為:
abc*+de*f+g*+
棧的情況為:空
至此,中綴表達式轉后綴已經全部完成,結果為abc*+de*f+g*+
。
三、代碼實現
借助C++的stack實現
//中綴表達式轉后綴 #include<iostream> #include<string> #include<stack> using namespace std; int prio(char op) //給運算符優先級排序 { int priority; if (op == '*' || op == '/') priority = 2; if (op == '+' || op == '-') priority = 1; if (op == '(') priority = 0; return priority; } bool Trans(string &str,string &str1) //引用傳遞 { stack<char> s; //定義一個char類型的棧s int i; for (i = 0; i<str.size(); i++) { if (str[i] >= '0' && str[i] <= '9'||str[i] >= 'a' && str[i] <= 'z') //如果是數字,直接入棧 { str1+=str[i]; } else //否則不是數字 { if (s.empty()) //棧空則入站 s.push(str[i]); else if (str[i] == '(') //左括號入棧 s.push(str[i]); else if (str[i] == ')') //如果是右括號,只要棧頂不是左括號,就彈出並輸出 { while (s.top() != '(') { str1+= s.top(); s.pop(); } s.pop(); //彈出左括號,但不輸出 } else { while (prio(str[i]) <= prio(s.top())) //棧頂優先級大於等於當前運算符,則輸出 { str1+= s.top(); s.pop(); if (s.empty()) //棧為空,停止 break; } s.push(str[i]); //把當前運算符入棧 } } } while (!s.empty()) //最后,如果棧不空,則彈出所有元素並輸出 { str1+= s.top(); s.pop(); } return true; } int main() //主程序 { string infix; string postfix; cout << "請輸入中綴表達式:" << infix << endl; cin >> infix; Trans(infix,postfix); cout << "后綴表達式為:" << postfix << endl; return 1; }
測試通過!
四、考研例題
