#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
using namespace std;
stack<int> num;
stack<char> op;
//优先级表
unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };
void eval()//求值
{
int a = num.top();//第二个操作数
num.pop();
int b = num.top();//第一个操作数
num.pop();
char p = op.top();//运算符
op.pop();
int r = 0;//结果
//计算结果
if (p == '+') r = b + a;
if (p == '-') r = b - a;
if (p == '*') r = b * a;
if (p == '/') r = b / a;
num.push(r);//结果入栈
}
int main()
{
string s;//读入表达式
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (isdigit(s[i]))//数字入栈
{
int x = 0, j = i;//计算数字
while (j < s.size() && isdigit(s[j]))
{
x = x * 10 + s[j] - '0';
j++;
}
num.push(x);//数字入栈
i = j - 1; //j最后停在了不是数字的位置,i=j-1即将数字最后一位给i。然后还要执行外面for循环里的i++,i=j-1才能让for继续正常进行
}
//左括号无优先级,直接入栈
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;
}
代码如上 ,为了简单我就拷贝了别人的代码
分析两个while :
其中是 71 行的 while , 另一个是 76 行的 while
假设 这两个 while 都用 if , 为什么不行呢 ? 我们通过如下样例分析
输入样例 : 1 - 1 * 2 + 1
最后会得到以下结果 :
num : 1 2 1
op : - +
我们知道, 如果第76行不用while的话,那么是没办法将剩下的表达式计算完的,因为它计算了2+1然后就结束了,所以这里首先就是为什么76行不可以用if的原因,接下来分析为什么71行不可以用if
原因在于,那我们将+号入栈的时候,因为入栈的时候,如果栈顶的符号比要入栈的符号的优先级大或者相等的时候,我们就要进行计算对吧,那如果用if的话,是不是只能保证计算一次,看我们的输入样例,如果是if的话,那么只会计算1乘2,这里当然没问题,但是当+号入栈的时候,我们不仅要计算1乘2等于2,还要计算1-2等于-1,也就是说,我们要计算出当+号入栈之前,所有比+号大或者相等的所有运算符,就类似于样例中的乘号和减号,而不是只计算一个
完 !!! 希望大家可以明白