题目描述
输入一个中缀表达式(由 0 ~ 9 组成的运算数、加减乘除四种运算符、左右小括号组成。
注意 -
也可作为负数的标志,表达式以 @
作为结束符),判断表达式是否合法,如果不合法,请输出 NO
;
否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。
注意:必须用栈操作,不能直接输出表达式的值。
输入格式
一行为一个以 @
结束的字符串。
输出格式
如果表达式不合法,请输出 NO
,要求大写。
如果表达式合法,请输出计算结果。
输入样例
1+2*8-9@
输出样例
8
题解
stack:
不合法情况
:
- 多个运算符直接相邻,例如
1*2+-3
; - 左右括号不匹配,例如
1*)(2+3)-4
;
解题步骤
:
- 如果是数字:直接压入
数字栈
中; - 如果是
(
:直接压入字符栈
中; - 如果是
)
:就将括号内的表达式计算完; - 如果是运算符:若当前运算符的优先级 ≤ 前一个运算符的优先级,那么就计算前面的,再将当前运算符加入
字符栈
中;
特殊情况
:
减号
:如1 - 2 + 3
,此时无需特殊处理;负号
:如-1 - 2 + 3
和(1 + 2) * (-3 + 4)
,此时应该把-1
和-3
加入数字栈
中;
#include <iostream>
#include <stack>
#include <map>
using namespace std;
stack<int> num;
stack<char> op;
map<char, int> Hash;
bool is_op(char c)
{
return c == '+' || c == '-' || c == '*' || c == '/';
}
bool check1(string s)
{
for (int i = 1; i < s.size() - 1; i ++)
if(is_op(s[i]) && is_op(s[i - 1])) return true;
return false;
}
bool check2(string s)
{
stack<char> stk;
for (int i = 0; i < s.size() - 1; i ++)
{
if(s[i] != '(' && s[i] != ')') continue;
else if(stk.empty()) stk.push(s[i]);
else if(stk.top() == '(' && s[i] == ')') stk.pop();
else stk.push(s[i]);
}
return stk.empty();
}
void cal()
{
int b = num.top(); num.pop();
int a = num.top(); num.pop();
char c = op.top(); op.pop();
if(c == '+') num.push(a + b);
if(c == '-') num.push(a - b);
if(c == '*') num.push(a * b);
if(c == '/') num.push(a / b);
}
int main()
{
string s;
getline(cin, s);
if(check1(s) || !check2(s))
{
cout << "NO" << endl;
return 0;
}
Hash['+'] = Hash['-'] = 1;
Hash['*'] = Hash['/'] = 2;
for (int i = 0; i < s.size() - 1; i ++)
{
if(s[i] >= '0' && s[i] <= '9')
{
int j = i, n = 0;
while(j < s.size() && s[j] >= '0' && s[j] <= '9') n = n * 10 + (s[j ++] - '0');
num.push(n);
i = j - 1;
}
else if(s[i] == '(')
{
op.push(s[i]);
}
else if(s[i] == ')')
{
while(op.top() != '(') cal();
op.pop();
}
else
{
while(op.size() && op.top() != '(' && Hash[op.top()] >= Hash[s[i]]) cal();
if(s[i] == '-' && (!i || s[i - 1] == '('))
{
int j = i + 1, n = 0;
while(j < s.size() && isdigit(s[j])) n = n * 10 + (s[j ++] - '0');
num.push(-n);
i = j - 1;
}
else op.push(s[i]);
}
}
while(op.size()) cal();
cout << num.top() << endl;
return 0;
}
ps:其实测试数据里并没有负数的情况 😅