C++算法之逆波兰表达式

逆波兰式,(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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值