题目:给定一个表达式,其中运算符仅包含 +,-,*,/
(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。
注意:
- 数据保证给定的表达式合法。
- 题目保证符号
-
只作为减号出现,不会作为负号出现,例如,-1+2
,(2+2)*(-(1+1)+2)
之类表达式均不会出现。 - 题目保证表达式中所有数字均为正整数。
- 题目保证表达式在中间计算过程以及结果中,均不超过 231−1231−1。
- 题目中的整除是指向 00 取整,也就是说对于大于 00 的结果向下取整,例如 5/3=15/3=1,对于小于 00 的结果向上取整,例如 5/(1−4)=−15/(1−4)=−1。
- C++和Java中的整除默认是向零取整;Python中的整除
//
默认向下取整,因此Python的eval()
函数中的整除也是向下取整,在本题中不能直接使用。 -
输入格式
共一行,为给定表达式。
输出格式
共一行,为表达式的结果。
数据范围
表达式的长度不超过 105105。
输入样例
-
(2+2)*(1+1)
-
输出样例:
-
8
思路:
定义数据栈和操作符栈
核心就是对操作符进行一个优先级的划分,先说说没有括号的情况
先说说结论:
1)如果栈顶是+,即将入栈的是+,则先计算,再入栈;
2)如果栈顶是+,即将入栈的是*,直接入栈;
3)如果栈顶是*,即将入栈的是+,则先计算,再入栈
4)如果栈顶是*,即将入栈的是*,则先计算,再入栈
没有括号时候
ex 1+3+5*7+4
模拟一遍
数据栈: 1 3
操作栈: +
这个时候遇到了+号
所以要先计算再入栈
于是
数据栈: 4
操作栈: +
到后面的5时(因为操作栈顶元素是+ 入栈的是* 栈顶元素不如入栈元素的优先级高,所以不计算直接入栈)
数据栈: 4 5
操作栈: + *
到后面+号前
数据栈: 4 5 7
操作栈: + *
到+号时候 吧操作栈里面所有优先级比+号大的都计算完成 再入栈
数据栈: 39
操作栈: +
最后到4
数据栈:39 4
操作栈: +
此时跳出循环 但是操作栈不为空 说明还有的操作没做完要继续做
如果有括号
(2*2)+(1+1)
首先说明一点 我们在m中 没有定义( 号的优先级的 但是后面进行了查询 所以m中会自动添加 {‘(’,0} 优先级默认是0
如果是(我们直接加入到操作栈中就好了 , 直到我们碰到了 )时候 ,直接开始计算括号里面的内容 知道操作符遇到了(时候截止。
一些细节的处理代码注释上面有 !!!
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
stack<ll> nums;//数字栈
stack<char> ops;//操作数栈
unordered_map<char,int> m={{'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };
//定义优先级
void caculate(){
ll a=nums.top();
nums.pop();
ll b=nums.top();
nums.pop();
char op=ops.top();
ops.pop();
ll res;
if (op == '+') res = b + a;
if (op == '-') res = b - a;
if (op == '*') res = b * a;
if (op == '/') res = b / a;
nums.push(res);
}
int main(){
string s;
cin>>s;
for(int i=0;i<s.size();i++){
if(s[i]>='0'&&s[i]<='9'){
//这里需要处理1000 这样的数字
// ll x = 0, j = i;
// while (j < s.size() && isdigit(s[j])){
// x = x * 10 + s[j] - '0';
// j++;
// }
// cout<<j<<endl;
// nums.push(x);
// i = j - 1;
//还原 说明这个数字已经到了第几位了 指向数字的下一个位置 为什么减去一捏
/*ex 1000+10
i=0 j=0
j=1 x=1
j=2 x=10
j=3 x=100
j=4 x=1000
i=j-1 i=3指向1000最后面一个0 然后该if条件跳出 大循环里i++
*/
//也可以用字符串来处理
ll x=0,j=i;
while(j<s.size()&&isdigit(s[j]))
j++;
string ts=s.substr(i,j);
x=stol(ts);
nums.push(x);
i=j-1;
}
if(s[i]=='('){
ops.push(s[i]); //这里m中没有定义但是 默认{{'(',0}};
}
if(s[i]==')'){
while(ops.top()!='(') caculate();
ops.pop();
}
if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
//为什么是while 自己推一遍1+5*2+4
while(ops.size()&&m[ops.top()] >= m[s[i]]) //当且仅当栈顶的元素优先级比 入栈op低的时候才会op入栈 else 先计算
caculate();
ops.push(s[i]);
}
}
while (ops.size()) caculate();//剩余的进行计算
cout << nums.top() << endl;//输出结果
}
可能出现的问题:
问题一:当数字是1001 时候该如何读入数据栈中?
代码中的注释有两种方法,一种用数学,二用string 去处理的。
问题二:四则运算的规则怎么实现的?
根据是否在栈中和+ -,* / ,的运算顺序 来划分优先级
问题三:括号如何处理的?
如果是( 我们直接放入栈中 ,如果)的话那么我们开始倒出操作栈中的操作符直到是(为止