計算中綴表達式是一個特別經典的關於棧的算法題,幾乎全部的數據結構教材中都會涉及,並且不少公司面試或者筆試的時候會把這道題做爲一個考點。所以,他的重要程度就不言而喻,下面 是關於表達式求值的一個總結。ios
題目: 輸入一箇中綴表達式計算表達式的結果。c++
輸入的前提假設:面試
(1)只考慮+,-,*,/這四種運算符,中綴表達式只有一種括號:()。算法
(2)輸入的中綴表達式只有整數,沒有小數。數據結構
(3)假定輸入是合法的。spa
爲了按部就班,此處先討論如何將中綴表達式轉化爲後綴表達式,在討論如何計算後最表達式,在前二者的基礎上,討論如何直接計算中綴表達式的結果。對於上面各表達式的概念再也不贅述。.net
一.中綴表達式轉化爲後綴表達式code
中綴表達式轉化爲後綴表達式式須要一個臨時棧S暫存運算符。blog
首先將各運算符的優先級排列,(數字越大優先級越高):get
1:(
2:+ -
3:* /
4.:)
對輸入的中綴表達式從左到右遍歷:
僞代碼:
(1)若是遇到數字,直接添加到後綴表達式末尾。
(2)若是遇到+ - * /:
先判斷棧是否爲空。如果,則將此運算壓入棧。若不是,則查看當前 棧頂元素。若棧頂元素的優先級大於或等於此操做符級別,則彈出棧頂元素,將棧頂元素添加到後綴表達式後面,並繼續上面的判斷。若是不知足上述的判斷,或棧爲空,將這個運算符入棧。
(3)若是遇到左括號,直接入棧。若是遇到右括號,彈出左括號前的全部操做符,並將左括號彈出。(右括號不如棧)
(4)字符遍歷結束,若是棧不爲空,則彈出棧中全部的操做符,將他們添加到後綴表達式的末尾,知道棧爲空。
二.計算後綴表達式
僞代碼: 準備一個數字棧,從左到右掃描表達式,若是是數字就入棧。若是是符號,從數字棧中彈出兩個數字,第一個取出的數字爲右運算數,第二個爲左運算數,進行運算。而後將運算結果放入數字棧中,如此反覆直到讀完整個表達式,留在數字棧中的數字就是最終結果。
默認:輸入的表達式中的全部的的數都是0——9的 整數,運算結果也爲整數。
#include<bits/stdc++.h> using namespace std; int Get_Priority(char ch) { if(ch=='(') return 1; else if(ch=='-'||ch=='+') return 2; else if(ch=='*'||ch=='/') return 3; else return 4; } /* 中綴表達式轉後綴表達式 */ string Get_Hou(string s) { stack<char>My_Stack; int size=s.size(); int i=0; string res="";///用於保存轉化後的結果 char temp; while(i<size) { ///若爲數字直接添加到後綴表達式的後面 if(s[i]>='0'&&s[i]<='9') { res.push_back(s[i]); } else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/') { if(My_Stack.empty())///若棧爲空,直接將運算符進棧 { My_Stack.push(s[i]); } else///否者若棧頂的優先級大於或等於當前的優先級,重複出棧並加入到後綴表達式末尾 { while(!My_Stack.empty()) { temp=My_Stack.top(); if(Get_Priority(temp)>=Get_Priority(s[i])) { res.push_back(temp); My_Stack.pop(); } else break; } My_Stack.push(s[i]);///將當前運算符進棧 } } else { if(s[i]=='(') My_Stack.push(s[i]); ///若爲作左括號直接進棧 else///不然,將棧中的元素所有出棧知道碰見左括號 { while(My_Stack.top()!='(') { temp=My_Stack.top(); res.push_back(temp); My_Stack.pop(); } My_Stack.pop();///刪除左括號後綴表達式和前綴表達式不存在括號,位置即體現了優先級 } } i++; } ///遍歷完後若棧非空彈出全部的元素 while(!My_Stack.empty()) { temp=My_Stack.top(); res.push_back(temp); My_Stack.pop(); } return res; } /* 計算後綴表達式 */ int calculate(string s) { stack<int>My_Stack; int size=s.size(); int num1,num2,num3; for(int i=0;i<size;i++) { if(s[i]>='0'&&s[i]<='9') { My_Stack.push(s[i]-'0'); } else { num2=My_Stack.top(); My_Stack.pop(); num1=My_Stack.top(); My_Stack.pop(); switch(s[i]) { case '+': num3=num1+num2; break; case '-': num3=num1-num2; break; case '*': num3=num1*num2; break; case '/': num3=num1/num2; break; } My_Stack.push(num3); } } return My_Stack.top(); } int main() { string s="1+(2-3)*4+4/2"; cout<<"中綴表達式:"<<endl<<s<<endl; string res=Get_Hou(s); cout<<"後綴表達式:"<<endl<<res<<endl; int num_res=calculate(res); cout <<"後綴表達式計算結果:"<< endl << num_res << endl; return 0; }
參考博客,此段代碼摘自:https://blog.csdn.net/sinat_27908213/article/details/80273557
#include<iostream> #include<string> #include<stack> using namespace std; int getPriority(char ch) { //獲取優先級 if (ch == '(') return 1; else if (ch == '+' || ch == '-') return 2; else if (ch == '*' || ch == '/') return 3; else return 4; } void calculate(stack<double> &mystack, char operation) { double num1, num2, num3; num2 = mystack.top(); mystack.pop(); num1 = mystack.top(); mystack.pop(); if (operation == '+') { num3 = num1 + num2; } else if (operation == '-') { num3 = num1 - num2; } else if (operation == '*') { num3 = num1 * num2; } else if (operation == '/') { num3 = num1 / num2; } mystack.push(num3); } double calculator(string str) { //計算中綴表達式,默認輸入是合法的 stack<double> mystack_number; stack<char> mystack_operation; int i = 0, j; int size = str.size(); char tmp_operation; string tmp_num; while (i < size) { if (str[i] >= '0' && str[i] <= '9') { j = i; while (j < size && str[j] >= '0' && str[j] <= '9') { j++; } tmp_num = str.substr(i, j - i); mystack_number.push(atoi(tmp_num.c_str())); i = j; } else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') { if (mystack_operation.empty()) { mystack_operation.push(str[i]); } else { while (!mystack_operation.empty()) { tmp_operation = mystack_operation.top(); if (getPriority(tmp_operation) >= getPriority(str[i])) { //計算 calculate(mystack_number, tmp_operation); mystack_operation.pop(); } else break; } mystack_operation.push(str[i]); } i++; } else { if (str[i] == '(') mystack_operation.push(str[i]); else { while (mystack_operation.top() != '(') { tmp_operation = mystack_operation.top(); //計算 calculate(mystack_number, tmp_operation); mystack_operation.pop(); } mystack_operation.pop(); } i++; } } //遍歷完後,若棧非空,彈出全部元素 while (!mystack_operation.empty()) { tmp_operation = mystack_operation.top(); //計算 calculate(mystack_number, tmp_operation); mystack_operation.pop(); } return mystack_number.top(); } int main() { string str = "1+(2-3)*4+10/2+2*2+2+2/5"; cout << "中綴表達式爲:" << endl << str << endl; double num_res = calculator(str); cout << "計算結果:" << endl << num_res << endl; system("pause"); return 0; }