ACWING151. 表达式计算4(表达式解析)

给出一个表达式,其中运算符仅包含+,-,*,/,^(加 减 乘 整除 乘方)要求求出表达式的最终值。

数据可能会出现括号情况,还有可能出现多余括号情况。

数据保证不会出现大于或等于231的答案。

数据可能会出现负数情况。

输入格式
输入仅一行,即为表达式。

输出格式
输出仅一行,既为表达式算出的结果。

输入样例:
(2+2)^(1+1)
输出样例:
16

思路:
中缀表达式转后缀,转的过程要注意符号的先后性,括号也可以看做是运算符,只不过运算方法不一样,要先计算括号里面的,那么左括号优先级是最高的,右括号优先级是最低的(当遇到左括号的时候括号内元素计算结束)。否则把优先性高的符号入队列(后缀表达式)。优先性相同,优先存储先出现的运算符。

但是本题比较麻烦的是数字可以多位是负数,括号可以多余。这方面的细节还是挺难处理的。

多位数字:每输完一次数字加上一个’#'表示数字结束

负数:当出现 ’-‘ 且栈中只有一个元素,那么把这个元素取负再放入栈

括号多余:如果出现 )1( 之类不合理的情况那我也没办法搞了。唯一能处理的就是多余的情况,这意味着是左右括号出现重复的情况,比如((((,你把它预处理成(就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <cctype>
using namespace std;

const int maxn = 2e5 + 7;
char ss[maxn],s[maxn];
map<char,int>mp;
stack<char>s1;//s1是字符,s2是后缀表达式,s3是用来计算后缀表达式的
stack<int>s3;
queue<char>s2;
int cnt;

int ppow(int x,int y)
{
    int res = 1;
    for(int i = 1;i <= y;i++)
    {
        res = res * x;
    }
    return res;
}

bool Isnum(char x)
{
    if(x <= '9' && x >= '0')return true;
    return false;
}

void trans()
{
    mp['+'] = mp['-'] = 1;
    mp['*'] = mp['/'] = 2;
    mp['^'] = 3;
    int len = cnt;
    for(int i = 1;i <= len;i++)
    {
        if(Isnum(s[i - 1]) && !Isnum(s[i]))
        {
            s2.push('#');
        }
        if(s[i] == '(')
        {
            s1.push('(');
        }
        else if(s[i] == ')')
        {
            while(s1.top() != '(')
            {
                s2.push(s1.top());
                s1.pop();
            }
            s1.pop();
        }
        else if('0' <= s[i] && s[i] <= '9')
        {
            s2.push(s[i]);
        }
        else
        {
            if(!s1.empty() && mp[s1.top()] >= mp[s[i]])
            {
                s2.push(s1.top());s1.pop();
            }
            s1.push(s[i]);
        }
    }
    if(Isnum(s[len]))s2.push('#');
    while(!s1.empty())
    {
        s2.push(s1.top());s1.pop();
    }
}

int cal()
{
    int num = 0;
    while(!s2.empty())
    {
        char now = s2.front();s2.pop();
        if('0' <= now && now <= '9')
        {
            num = num * 10 + now - '0';
            continue;
        }
        else if(now == '#')
        {
            s3.push(num);
            num = 0;
            continue;
        }
        else
        {
            if(s3.size() == 1)
            {
                if(now == '-')
                {
                    num = s3.top();s3.pop();
                    s3.push(-num);
                }
                continue;
            }
            int num1 = s3.top();s3.pop();
            int num2 = s3.top();s3.pop();//在先
            if(now == '-')
                num = num2 - num1;
            else if(now == '*')
                num = num2 * num1;
            else if(now == '/')
                num = num2 / num1;
            else if(now == '^')
                num = ppow(num2,num1);
            else if(now == '+')
                num = num2 + num1;
            s3.push(num);
            num = 0;
        }
    }
    return s3.top();
}



int main()
{
    scanf("%s",ss + 1);
    int len = strlen(ss + 1);
    cnt = 0;
    for(int i = 1;i <= len;i++)
    {
        if(ss[i] == ss[i - 1] && (ss[i] == '(' || ss[i] == ')'))
            continue;
        s[++cnt] = ss[i];
    }
    
    trans();

    printf("%d\n",cal());
    return 0;
}

发布了756 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104484877