思路:
1.准备双栈,一个压入数字,另一个压入运算符。
2.判断运算符优先级进行运算。(技巧:运算符栈按优先级形成单调递增)即当一个运算符入栈时,与栈顶元素比较。
1)如果栈顶运算符优先级高,那么计算栈顶运算符所对应的式子,此时就完成了运算符优先级高的先运算。
2)如果栈顶运算符优先级低,将当前运算符入栈。注意:运算规则是从左到右(后面会具体看解释)。
实现代码:
#include<iostream>
#include<map>
#include<stack>
using namespace std;
stack<int> is;
stack<char> cs;
void operation() //计算运算符栈顶所对应的式子
{
int x = is.top(); is.pop(); //运算符右值
int y = is.top(); is.pop(); //运算符左值
int c = cs.top(); cs.pop(); //运算符
int s;
if (c == '+') s = y + x;
if (c == '-') s = y - x;
if (c == '*') s = y * x;
if (c == '/') s = y / x;
is.push(s); //将得数压栈
}
int main()
{
map<char, int> m{ {'+',1},{'-',1},{'*',2},{'/',2} }; // 运算符优先级
string c;
cin >> c;
for (int i = 0; i < c.size(); i++)
{
int j = i,x = 0;
if (isdigit(c[i]))
{
while (j<c.size() && isdigit(c[j])) x = x * 10 + c[j++] - '0'; // 超过各位的数字
is.push(x); // 数字入栈
i = j - 1; // 更新i值
}
else if (c[i] == '(') cs.push(c[i]); // '('直接入栈
else if (c[i] == ')')
{
while (cs.top() != '(') operation(); // 将()中的元素全部计算完
cs.pop();
}
else //判断运算符
{
while (cs.size() && m[cs.top()] >= m[c[i]]) //栈顶运算符与当前运算符优先级比较
operation(); // /栈顶运算符比当前运算符优先级高时
cs.push(c[i]); // 将当前运算符入栈
}
}
while (!cs.empty()) operation(); // 剩余运算
cout << is.top() << endl;
}
这里重点解释下判断运算符:
while (cs.size() && m[cs.top()] >= m[c[i]]) //等号为了运算能从左往右进行,同一优先级先按左边计算
想一想这里可不可以是if
。
这里用while
是为了保证运算是从左往右执行的。
例:
3 - 2 * 7 + 2
while:
第一次:(
+
入栈时 )数字栈 :
7
2
3
运算符栈:*
-
第二次:
数字栈:
14
3
运算符符:-
循环结束
结果:
-11 + 2 = -9
if:
数字栈 :
7
2
3
运算符栈:*
-
数字栈:
2 14 3
运算符栈:+
-
结果:先计算栈顶元素
14 + 2 = 16
3 - 16 = -13
以上可以看出while
和 if
的区别,一个是左运算,一个是右运算。