逆波兰式,(RPN)也叫后缀表达式,即将运算符写在操作数之后 详细定义见百度百科
中缀表达式:(a+b)*c-(a+b)/e
转换为后缀表达式: ab+c*ab+e/-
中缀表达式相对于人类的思维结构来看简单易懂,但是对于计算机来看是非常复杂的结构,而将中缀表达式转换为后缀表达式,即逆波兰表达式,对计算机而言简单易懂
中缀表达式转后缀表达式的算法伪码
- 对中缀表达式进行遍历
- 遇到数字,直接入栈
- 遇到符号
- 如果当前栈为空,符号直接入栈
- 如果是"(",直接入栈
- 用当前符号和栈顶符号比较其优先级
- 当前符号>栈顶符号,当前符号入栈,continue
- 当前符号<=栈顶符号,栈顶符号出栈并输出,继续比较
- 把栈里面的符号都输出完了
- 遇到")",要一直出栈,直到遇到"("并完成出栈为止
后缀表达式进行计算
- 直接遍历
- 遇到数字进行压栈
- 遇到操作符直接从操作数栈里弹出两个数据进行计算,再将结果压入栈中
代码如下
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
class Solution {
public:
int calc(int left,int right,string sign){
int t;
if(sign=="+"){
t = left+right;
}else if(sign=="-"){
t = left-right;
}else if(sign=="*"){
t = left*right;
}else if(sign=="/"){
t = left/right;
}
return t;
}
bool Priority(string str,string tops){
if((str=="+"||str=="-")&&(tops=="*"||tops=="/"))
return true;
if(str == ")")
return false;
if(tops == "("&&str!=")")
return true;
return false;
}
vector<string> MidddleToEndExpr(vector<string>& expr){
vector<string> result;
stack<string> s;
for(string &str:expr){
//符号还是数字
if(str.size()==1&&(str=="+"||str=="-"||str=="*"||str=="/"||str=="("||str==")")){
while(1){
if(s.empty() || str=="("){//为空或者是左括号
s.push(str);
break;
}
string tops = s.top();
if(Priority(str,tops)){ //如果str>tops
s.push(str);
break;
}else{//如果str<=tops
s.pop();
if(tops=="("){break;}
result.push_back(tops);
}
}
}else{//数字,直接入栈
result.push_back(str);
}
}
//如果符号栈不为空,有符号,继续输入到result里
while(!s.empty()){
result.push_back(s.top());
s.pop();
}
return result;
}
int evalRPN(vector<string>& tokens) {
stack<int> temp;
for(string &str:tokens){
if(str.size()==1&&(str=="+"||str=="-"||str=="*"||str=="/")){
int right = temp.top();
temp.pop();
int left = temp.top();
temp.pop();
temp.push(calc(left,right,str));
}else{
temp.push(stoi(str));
}
}
return temp.top();
}
};
int main(){
Solution eva;
vector<string> expr;
vector<string> tokens;
expr.push_back("(");
expr.push_back("2");
expr.push_back("+");
expr.push_back("1");
expr.push_back(")");
expr.push_back("*");
expr.push_back("(");
expr.push_back("5");
expr.push_back("+");
expr.push_back("2");
expr.push_back(")");
tokens = eva.MidddleToEndExpr(expr);
for( string s:tokens){
cout<<s<<endl;
}
cout<<eva.evalRPN(tokens);
}