题解 | #表达式求值#

表达式求值

http://www.nowcoder.com/practice/c215ba61c8b1443b996351df929dc4d4

题目描述:
输入一个表达式(用字符串表示),求这个表达式的值。
保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

解题思路:使用两个stack,一个存放数字nums,一个存放操作符ops。
解题步骤如下
1、先将输入的string预处理成string数组(数组中存放的字符串,要么是符号,要么是数字),注意对于"-"既可能是负号也可能是减号,需要注意区分。
2、遍历step1生成的字符串数组,根据每次处理的string str,分情况讨论
3、str若是数字,直接push进nums
4、str若是(,直接push进ops
5、str若是),将ops一直出栈运算,直到ops栈顶是左括号。
6、str若是*,直接ops入栈。因为成人乘法前面可以接任何运算,倒序运算的时候不会影响结果。
7、str若是/,需要将前面的连除先运算了,比如8/4/2,必须先把第一个除法计算掉。
7、str若是+,需要将前面的乘除、减法运算掉
8、str若是-,需要将前面的乘除、减法运算掉
9、将string数组遍历结束之后,ops里面可能还有一些运算符。最后需要将ops里面所有的操作符依次弹出计算,最后nums只剩一个数字,即为最终结果。

实现细节原理需要注意:
1、一个符号入栈ops的前面是,和前面的运算相连之后,倒序运算也不会影响结果。
2、因为此题要求输入的字符串一定合法,所以省去了异常判断。但如果不能保证输入字符串一定合法,则代码中需要注意异常判断,如pop前判断非空。除法前判断除数非0.

献上粗糙的AC代码

using namespace std;
#include<iostream>
#include<string>
#include<vector>
#include<stack>
//将字符串分解为数字、符号
vector<string> split(string s){
    vector<string> res;
    while(s.size()){
        char ch=s[0];
        if(ch=='('||ch=='{'||ch=='['){
            res.push_back("(");
            s.replace(0,1,"");
        }else if(ch==')'||ch==']'||ch=='}'){
            res.push_back(")");
            s.replace(0,1,"");
        }else if(ch=='*'||ch=='/'||ch=='+'){
            res.push_back(s.substr(0,1));
            s.replace(0,1,"");
        }else if(ch=='-'){
            if(res.size()==0||res[res.size()-1]=="("){
                //如果是开头或者前面是括号,则是负号
                int len=1;
                while(len<s.size()&&(s[len]>='0'&&s[len]<='9'))
                    len++;
                res.push_back(s.substr(0,len));
                s.replace(0,len,"");
            }else{//仅仅是一个减号
                res.push_back("-");
                s.replace(0,1,"");
            }
        }else{//数字
            int len=0;
            while(len<s.size()&&(s[len]>='0'&&s[len]<='9'))
                len++;
            res.push_back(s.substr(0,len));
            s.replace(0,len,"");
        }
    }
    return res;
}
//取出并弹出两个操作数
vector<int> twoNum(stack<int>& nums){
    int b=nums.top();
    nums.pop();
    int a=nums.top();
    nums.pop();
    return {a,b};
}
char takeOp(stack<char>& ops){
    char op=ops.top();
    ops.pop();
    return op;
}
int solve(string s){
    vector<string> ss=split(s);
    //for(string x:ss)cout<<x<<"  ";  cout<<"\n";
    stack<int> nums;
    stack<char> ops;
    for(string str:ss){
        if(str=="(")ops.push('(');//左括号直接入符号栈
        else if(str==")"){//进行运算,直到符号栈遇到一个左括号
            while(ops.top()!='('){
                vector<int> ab=twoNum(nums);
                char op=takeOp(ops);
                int c=0;
                if(op=='+')c=ab[0]+ab[1];
                else if(op=='-')c=ab[0]-ab[1];
                else if(op=='*')c=ab[0]*ab[1];
                else c=ab[0]/ab[1];
                nums.push(c);
                //cout<<ab[0]<<op<<ab[1]<<"="<<c<<"\n";
            }
            ops.pop();//将那个左括号弹出
        }else if(str=="+"||str=="-"){
            //加号前面只能保留加号,遇到高优先级乘除、以及减法,都需要先把前面的计算掉
            while(ops.size()&&(ops.top()=='*'||ops.top()=='/'||ops.top()=='-')){
                vector<int> ab=twoNum(nums);
                char op=takeOp(ops);
                int c=0;
                if(op=='*')c=ab[0]*ab[1];
                else if(op=='/') c=ab[0]/ab[1];
                else c=ab[0]-ab[1];
                nums.push(c);
                //cout<<ab[0]<<op<<ab[1]<<"="<<c<<"\n";
            }
            if(str=="+")ops.push('+');
            else ops.push('-');
        }
        else if(str=="*")ops.push('*');
        else if(str=="/"){
            //除法前面不可以保留除号,因为不能连除。其他加减乘法均可以
            if(ops.size()&&ops.top()=='/'){
                ops.pop();
                vector<int> ab=twoNum(nums);
                int c=ab[0]/ab[1];
                nums.push(c);
                //cout<<ab[0]<<"/"<<ab[1]<<"="<<c<<"\n";
            }
            ops.push('/');
        }else nums.push(std::stoi(str));//数字直接入栈
    }
    while(ops.size()){//将符号栈运算清空
        vector<int> ab=twoNum(nums);
        char op=takeOp(ops);
        int c=0;
        if(op=='+')c=ab[0]+ab[1];
        else if(op=='-')c=ab[0]-ab[1];
        else if(op=='*')c=ab[0]*ab[1];
        else c=ab[0]/ab[1];
        nums.push(c);
        //cout<<ab[0]<<op<<ab[1]<<"="<<c<<"\n";
    }
    //cout<<"-----------\n"<<nums.top()<<"\n";
    return nums.top();
}
int main(){
    string s;
    cin>>s;
    cout<<solve(s);
    return 0;
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务