3302. 表达式求值
给定一个表达式,其中运算符仅包含 +,-,*,/
(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。
注意:
- 数据保证给定的表达式合法。
- 题目保证符号
-
只作为减号出现,不会作为负号出现,例如,-1+2
,(2+2)*(-(1+1)+2)
之类表达式均不会出现。 - 题目保证表达式中所有数字均为正整数。
- 题目保证表达式在中间计算过程以及结果中,均不超过 231−1
- 。
- 题目中的整除是指向 0
- 取整,也就是说对于大于 0 的结果向下取整,例如 5/3=1,对于小于 0 的结果向上取整,例如 5/(1−4)=−1
- 。
- C++和Java中的整除默认是向零取整;Python中的整除
//
默认向下取整,因此Python的eval()
函数中的整除也是向下取整,在本题中不能直接使用。
输入格式
共一行,为给定表达式。
输出格式
共一行,为表达式的结果。
数据范围
表达式的长度不超过 105
。
输入样例:
(2+2)*(1+1)
输出样例:
8
第一种是算法笔记上的写法:
/**
* 将中缀表达式转换为后缀表达式可以直接从左到右进行运算,不用考虑中间
* 运算符的优先级。
*/
/**
* 将中缀表达式转换为后缀表达式可以直接从左到右进行运算,不用考虑中间
* 运算符的优先级。
*/
#include <iostream>
#include <queue>
#include <stack>
#include <map>
using namespace std;
struct Node
{
int num; //运算数
char op; //运算符
bool flag; //true表示操作数,false表示操作符
};
stack<Node> stk; //操作符栈
queue<Node> q; //后缀表达式
map<char,int> op; //将运算符优先级映射成数字,数字越大,优先级越高
void get_beh(string &str)
{
while(stk.size()) //清空栈的内容
stk.pop();
Node tm;
for(int i=0;i<str.size();)
{
if(isdigit(str[i]))
{
tm.flag=true;
tm.num=str[i++]-'0';
while(i<str.size() && isdigit(str[i]))//也许运算数并不止一位
tm.num=tm.num*10+str[i++]-'0';
q.push(tm);
}
else
{
if(str[i] == ')')
{
Node t=stk.top();
stk.pop();
while(t.op != '(')
{
q.push(t);
t=stk.top();
stk.pop();
}
++i; //别忘了将i右移一位
continue;
}
tm.flag=false;
while(!stk.empty() && op[stk.top().op] >= op[str[i]] && stk.top().op != '(')
{ //当栈顶的运算符优先级大于或等于该运算符
q.push(stk.top());
stk.pop();
}
tm.op=str[i++];
stk.push(tm);
}
}
while(stk.size()) //也许栈还有运算符,加入后缀表达式中
{
q.push(stk.top());
stk.pop();
}
}
int cal()
{
while(q.size()) //只要后缀表达式中还有值
{
Node tm = q.front(); //取出队首元素
q.pop();
if(tm.flag == true)
stk.push(tm);
else
{
int temp2=stk.top().num;
stk.pop(); //栈顶是第二个操作数
int temp1=stk.top().num;
stk.pop(); //栈的第二个元素才是第一个运算数
if(tm.op == '+')
tm.num=temp1+temp2;
else if(tm.op == '-')
tm.num=temp1-temp2;
else if(tm.op == '*')
tm.num=temp1*temp2;
else
tm.num=temp1/temp2;
stk.push(tm); //将得到的结果加入栈内
}
}
return stk.top().num; //只要是正确的运算式,那么栈此时有唯一一个元素,也是该算式的答案
}
int main()
{
op['+'] = op['-'] =1;
op['*'] = op['/'] =2;
op['('] = 5;
op[')'] = 6;
string str;
getline(cin,str);
string temp;
for(int i=0;i<str.size();++i)
if(!isspace(str[i]))
temp+=str[i]; //将空格统统去掉
str=temp;
get_beh(str);
cout << cal() << endl;
return 0;
}
第二种写法跟着y总写的:
#include <iostream>
#include <algorithm>
#include <map>
#include <stack>
using namespace std;
stack<int> num;
stack<char> op;
void cal()
{
int t2=num.top(); num.pop();
int t1=num.top(); num.pop();
char ch =op.top(); op.pop();
int res;
if(ch == '+')
res = t1+t2;
else if(ch == '-')
res = t1-t2;
else if(ch == '*')
res = t1*t2;
else
res = t1/t2;
num.push(res);
}
int beh(string &s)
{
map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
for(int i=0;i<s.size();++i)
{
if(isdigit(s[i]))
{
int j=i,n=0;
while(j<s.size() && isdigit(s[j]))
n = n*10 + s[j++]-'0';
num.push(n);
i=j-1;
}
else if(s[i] == '(')
op.push(s[i]);
else if(s[i] == ')')
{
while(op.top() != '(')
cal();
op.pop();
}
else
{
while(op.size() && pr[op.top()]>=pr[s[i]] && op.top()!='(')
cal();
op.push(s[i]);
}
}
while(op.size())
cal();
return num.top();
}
int main()
{
string str;
getline(cin,str);
cout << beh(str) << endl;
return 0;
}