算法1:栈维护(模拟) $O(n)$
//整体是栈模拟,一个栈存储数字,一个栈存储符号;
//左括号入栈,右括号一直算到左括号,然后出栈左括号,数字入栈
//符号,栈顶符号优先级>=当前符号就一直计算
//细节处理, -是负号还是减号,-前面不是数字且不是) 就是负号,在数字栈加入一个0
//有多余的括号,先在左边加入足够多的左括号,
//最后在清空符号栈
#include <bits/stdc++.h>
using namespace std;
stack<int> nums;
stack<char> ops;
string s;
unordered_map<char, int> mp = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}};
void cal() {
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
char c = ops.top(); ops.pop();
int res;
if (c == '+') res = a + b;
if (c == '-') res = a - b;
if (c == '*') res = a * b;
if (c == '/') res = a / b;
if (c == '^') res = pow(a, b);
nums.push(res);
}
int main() {
cin >> s;
string t(s.size(), '(');
s = t + s + ')'; //预处理括号,保证左括号一定足够右括号匹配的
for (int i = 0; i < s.size(); ++ i)
if (s[i] == '(') ops.push(s[i]);
else if (s[i] >= '0' && s[i] <= '9') {
int j = i, t = 0;
while (s[j] >= '0' && s[j] <= '9') {
t = t*10 + s[j] - '0';
j++;
}
i = j-1;
nums.push(t);
} else if (s[i] == '-' && !(s[i-1] >= '0' && s[i-1] <= '9' || s[i-1] == ')')) { //特判出是负号
nums.push(0); //增加一个0 相当于是把x 变为 0-x 形式
ops.push(s[i]);
} else if (s[i] == ')') {
while (ops.top() != '(') cal();
ops.pop(); //一直算到遇到左括号,最后在弹出左括号
} else { //+ - * / ^
while (mp[ops.top()] >= mp[s[i]]) cal();
ops.push(s[i]); //最后在把si负号加入到栈中
}
while (ops.size()) {
if (ops.top() == '(') ops.pop();
else cal();
}
cout << nums.top();
return 0;
}
参考题解: https://www.acwing.com/solution/content/120962/
把括号预处理到匹配: https://www.acwing.com/solution/content/64760/