给出一个表达式,其中运算符仅包含+,-,*,/,^(加 减 乘 整除 乘方)要求求出表达式的最终值。
数据可能会出现括号情况,还有可能出现多余括号情况。
数据保证不会出现大于或等于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;
}