中缀表达式求值
思路: 用哈希表映射运算符的优先级,两栈(数字栈和运算符栈)来动态维护整个表达式使其达到最简化。
步骤:
- 若是数字就将整个数字加进数字栈
- 若是
(
,就将左括号加入运算符栈- 若是
)
,就计算出()
中的表达式,这里从栈中取出元素是从右到左取出的,要注意-,/
前后的数字不能反- 若是运算符就直接算,直至运算符栈为空
#include <iostream>
#include <algorithm>
#include <stack>
#include <unordered_map>
using namespace std;
//哈希映射一下运算符的优先级
unordered_map<char, int> p{{'-', 1}, {'+', 1}, {'*', 2}, {'/', 2}};
//两栈,num存数字,op存运算符和()
stack<int> num;
stack<char> op;
//计算相邻两个数
void eval()
{
/*这里的a,b插入num栈的运算顺序不能反,对于*和+无所谓,但对于-和/来说,
顺序就不能反,栈中取出后是从右边往左边算*/
int b = num.top(); num.pop();
int a = num.top(); num.pop();
char c = op.top(); op.pop();
if(c == '+') num.push(a + b);
else if(c == '-') num.push(a - b);
else if(c == '*') num.push(a * b);
else if(c == '/') num.push(a / b);
}
int main()
{
string s;
cin >> s;
for(int i = 0; i < s.size(); i ++ )
{
if(isdigit(s[i])) //如果是数字
{
int j = i, x = 0; //这里就相当于双指针,若s[i]是数字,就找到不是数字为止,加到栈中
while(j < s.size() && isdigit(s[j]))
x = x * 10 + s[j ++ ] - '0';
num.push(x);
i = j - 1; //加完后更新i,防止重复加入,j - 1后经过i++,i刚好指向运算符
}
else if(s[i] == '(') op.push(s[i]); //左括号,直接加进去
else if(s[i] == ')') //右括号,进行计算括号里的内容,直至消掉括号
{
while(op.size() && op.top() != '(')
eval();
op.pop(); //删掉左括号
}
else //正常的运算符
{
//若是栈中运算符优先级>=所枚举到的,说明可以进行运算操作
while(op.size() && p[op.top()] >= p[s[i]]) //如果op.top()是左括号,将返回一个错误值
eval();
//操作完后或是不用操作,都将枚举到的运算发加入到op运算符栈
op.push(s[i]);
}
}
while(op.size()) eval(); //将没有算完的算完
cout << num.top() << endl;
return 0;
}