思路
很简单,就是维护数字和字符两个栈
-
读到数字,放入
-
读到字符,
- 字符等级高,直接放入
- 字符等级低,则把前面高的全都
eval
一遍(此时注意while
循环需要加上op.size()
判断),然后放入
-
读到左括号,放入,等待右括号
-
读到右括号,循环计算,直到读到左括号
- 计算之后需要手动弹出左括号
-
eval函数比较好理解,就是挑左右两个数和一个运算符
- 由于栈是动态维护的且遵循读入的顺序,所以只要存入弹出没有问题,那么配对计算是没有问题的
注意点
- 所有的弹出操作都在
eval
中进行,所以主干不需要维护出栈- 除了
(
,需要在主程序中弹出,因为不会进入到eval
中
- 除了
while
的时候要加上op.size()
的判断,不然会SE
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>
#include <unordered_map>
using namespace std;
unordered_map<char, int> h {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
stack<int> num;
stack<char> op;
void eval()
{
int b = num.top();
num.pop();
int a = num.top();
num.pop();
char c = op.top();
op.pop();
int x = 0;
if (c == '+') x = a + b;
else if (c == '-') x = a - b;
else if (c == '*') x = a*b;
else if (c == '/') x = a/b;
num.push(x);
return ;
}
int main ()
{
string s;
cin >> s;
for (int i = 0; i < s.size(); i ++)
{
if (isdigit(s[i]))
{
int x = 0;
int j = i;
while (isdigit(s[j]))
{
x = x*10 + s[j] - '0';
j ++;
}
num.push(x);
i = j-1;
}
else if (s[i] == '(')
{
op.push(s[i]);
}
else if (s[i] == ')')
{
while (op.top() != '(')
{
eval();
}
op.pop();
}
else
{
while (op.size() && h[op.top()] >= h[s[i]])
{
eval();
}
op.push(s[i]);
}
}
while (op.size()) eval();
cout << num.top() << endl;
return 0;
}