中缀表达式转化为后缀表达式
一、從應(yīng)對(duì)考試角度來(在最快的時(shí)間內(nèi)得出最準(zhǔn)確的答案)
首先我們應(yīng)該知道,要想將中綴轉(zhuǎn)化為后綴,需要借助堆棧實(shí)現(xiàn)。(不準(zhǔn)備畫圖了,畫圖有點(diǎn)浪費(fèi)時(shí)間)我會(huì)用最簡單明了的語言使讀者弄懂。[舉個(gè)例子吧:比如將:2*(9+6/3-5)+4轉(zhuǎn)化為后綴表達(dá)式2 9 6 3 / +5 -? * 4 +? ? ]
1、任何中綴表達(dá)式都由運(yùn)算數(shù),運(yùn)算符,括號(hào)(大,中,小),這三部分組成。
2、從中綴表達(dá)式的左邊開始掃描(腦中自己想像的),若遇到運(yùn)算數(shù)時(shí),則直接將其輸出(不壓入堆棧)。
3、若遇到左括號(hào),則將其壓棧。
4、若遇到右括號(hào),表達(dá)括號(hào)內(nèi)的中綴表達(dá)式已經(jīng)掃描完畢。這時(shí)需將棧頂?shù)倪\(yùn)算符依次彈出并輸出,直至遇到左括號(hào)[左括號(hào)彈出但不輸出]。
5、若遇到的是運(yùn)算符:a、如果該運(yùn)算符的優(yōu)先級(jí)大于棧頂運(yùn)算符的優(yōu)先級(jí)時(shí),將其壓棧
????????????????????????????????? ? b、如果該運(yùn)算符的優(yōu)先級(jí)小于棧頂運(yùn)算符的優(yōu)先級(jí)時(shí),將棧頂運(yùn)算符彈出并輸出,接著和新的棧頂運(yùn)算 符比較,若大于,則將其壓棧,若小于,繼續(xù)將棧頂運(yùn)算符彈出并輸出......(一直遞歸下去,直至運(yùn)算符大于棧頂云算符為止)。
6、最后一步,若掃描到中綴表達(dá)式的末尾[即掃描結(jié)束],若堆棧中還有存留的運(yùn)算符依次彈出并輸出即可。
原文:https://blog.csdn.net/coder_dacyuan/article/details/79941743
?
CODE:
/* 中綴轉(zhuǎn)后綴C++代碼實(shí)現(xiàn)(比較方便) 1.遇到操作數(shù):添加到后綴表達(dá)式中或直接輸出 2.棧空時(shí):遇到運(yùn)算符,直接入棧 3.遇到左括號(hào):將其入棧 4.遇到右括號(hào):執(zhí)行出棧操作,輸出到后綴表達(dá)式,直到彈出的是左括號(hào) 注意:左括號(hào)不輸出到后綴表達(dá)式 5.遇到其他運(yùn)算符:彈出所有優(yōu)先級(jí)大于或等于該運(yùn)算符的棧頂元素,然后將該運(yùn)算符入棧 6.將棧中剩余內(nèi)容依次彈出后綴表達(dá)式 */#include<iostream> #include<stack> #include<queue> #include<map> #include<string> #include<cstdio> #define MAX 100 using namespace std;//設(shè)置優(yōu)先級(jí)(注意默認(rèn)操作數(shù)的優(yōu)先級(jí)最高,即其不需要進(jìn)棧,進(jìn)棧的都是運(yùn)算符) map<char, int> p;//一些初始化******************************************** struct Node{double num;//操作數(shù)char op;//操作符bool flag;//true表示操作數(shù),false表示操作符 }; typedef struct Node node;stack<node> s;//操作符棧 stack<node> s1;//存放操作數(shù)的,為了計(jì)算后綴表達(dá)式的值 queue<node> q;//后綴表達(dá)式隊(duì)列//****************************************************** //中綴轉(zhuǎn)后綴函數(shù) void change(string str){node temp;for (int i = 0; i < str.length();){if (str[i] == '('){//3.遇到左括號(hào):將其入棧temp.flag = false;temp.op = str[i];s.push(temp);i++;}else if (str[i] == ')'){//4.遇到右括號(hào):執(zhí)行出棧操作,輸出到后綴表達(dá)式,直到彈出的是左括號(hào)while (!s.empty() && s.top().op != '('){q.push(s.top());s.pop();}s.pop();//彈出左括號(hào)i++;}else if (str[i] >= '0'&&str[i] <= '9'){//如果是數(shù)字temp.flag = true;temp.num = str[i] - '0';i++;//后移一位,因?yàn)閿?shù)字不一定是個(gè)位數(shù)while (i < str.length() && str[i] >= '0'&&str[i] <= '9'){temp.num = temp.num * 10 + (str[i] - '0');i++;}q.push(temp);//操作數(shù)進(jìn)入后綴表達(dá)式}else{//如果是操作符//5.遇到其他運(yùn)算符:彈出所有優(yōu)先加大于或等于該運(yùn)算符的棧頂元素,然后將該運(yùn)算符入棧temp.flag = false;while (!s.empty() && p[s.top().op] >= p[str[i]]){q.push(s.top());s.pop();}temp.op = str[i];s.push(temp);i++;}}//6.將棧中剩余內(nèi)容依次彈出后綴表達(dá)式while (!s.empty()){q.push(s.top());s.pop();} }//************************************************************* //后綴表達(dá)式的計(jì)算 /* 從左到右掃描后綴表達(dá)式 1)若是操作數(shù),就壓棧, 2)若是操作符,就連續(xù)彈出兩個(gè)操組數(shù) 3)棧頂?shù)闹导礊樗杞Y(jié)果 注:先彈出的是第一操作數(shù),后彈出的是第二操作數(shù) */ double calculate(){double num_a, num_b;//操作數(shù)a,bnode cur, temp;while (!q.empty()){//后綴隊(duì)列非空cur = q.front();//記錄隊(duì)首元素q.pop();if (cur.flag == true){//是操作數(shù)進(jìn)入棧s1.push(cur);}else{//是操作符就運(yùn)算num_b = s1.top().num;s1.pop();//彈出第二操作數(shù)num_a = s1.top().num;s1.pop();//彈出第一操作數(shù)temp.flag = true;if (cur.op == '+'){temp.num = num_a + num_b;}else if (cur.op == '-'){temp.num = num_a - num_b;}else if (cur.op == '*'){temp.num = num_a * num_b;}else{temp.num = num_a / num_b;}s1.push(temp);//把計(jì)算后的結(jié)果再次壓棧}}return s1.top().num;} //*************************************************************int main() {string str;p['+'] = p['-'] = 1;//通過hashmap賦值p['*'] = p['/'] = 2;cin >> str;change(str);//*****************************************************//中綴轉(zhuǎn)后綴/*while (!q.empty()){cur = q.front();if (cur.flag == true) cout << cur.num << " ";else cout << cur.op << " ";q.pop();}*/while (!s1.empty()){//初始化棧s1s1.pop();}double answer=calculate();cout << answer<<endl;return 0; }
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhangbuang/p/11177898.html
總結(jié)
以上是生活随笔為你收集整理的中缀表达式转化为后缀表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows自带反编译chm文件
- 下一篇: docker (centOS 7) 使用