时间限制: 1000 ms 内存限制: 65536 KB 提交数: 3759 通过数: 1268 【题目描述】
输入一个中缀表达式(由 0-9 组成的运算数、加 + 减 - 乘 * 除 / 四种运算符、左右小括号组成。注意 “-”
也可作为负数的标志,表达式以 “@” 作为结束符),判断表达式是否合法,如果不合法,请输出
“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。注意:必须用栈操作,不能直接输出表达式的值。
【输入】 一行为一个以 @结束的字符串。
【输出】 如果表达式不合法,请输出 “NO”,要求大写。
如果表达式合法,请输出计算结果。
【输入样例】 1+2*8-9@ 【输出样例】 8
思路
代码
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
using namespace std;
map<char, int> p;
struct Node
{
double num; //操作数
char op; //操作符
bool flag; //是否为操作数
};
stack<Node> st; //符号栈
stack<Node> sa; //存放操作数的栈,用来求后缀表达式的值
queue<Node> q;
void init()
{
p['+'] = p['-'] = 1;
p['*'] = p['/'] = 2;
}
/* 表达式中缀转后缀表达式
* 0. 从左到右边里所给的中缀字符串,执行接下来的步骤
* 1. 遇到操作数:直接添加到后缀表达式中/直接输出
* 2. 遇到运算符:首先把符号栈中,从栈顶开始循环输出,直到栈顶的运算符的优先级小于当前运算符的有限接,之后把当前运算符压入栈中
* 3. 遇到左括号:直接压入到符号栈中
* 4. 遇到右括号:把此事符号栈中的字符循环输出,直到遇到左括号,并且把左括号输出
*/
void change(string s)
{
int n = s.size() - 1;
Node tmp;
for(int i = 0; i < n; )
{
if(s[i] == '(')
{
tmp.flag = 0;
tmp.op = s[i];
st.push(tmp);
i ++;
}
else if(s[i] == ')')
{
while(st.size() && st.top().op != '(')
{
q.push(st.top());
st.pop();
}
st.pop();
i ++; // 把剩下的'('给弹出
}
else if(s[i] >= '0' && s[i] <= '9')
{
tmp.flag = 1;
tmp.num = s[i] - '0';
i ++; //后移一位因为数字可能不是一位!!!
while(i < n && s[i] >= '0' && s[i] <= '9')
{
tmp.num *= 10;
tmp.num += s[i] - '0';
i ++;
}
q.push(tmp); //操作数最后进入后缀表达式
}
else //遇到操作符,弹出栈顶优先级比该操作符大的运算符
{
tmp.flag = 0;
while(st.size() && p[s[i]] <= p[st.top().op])
{
q.push(st.top());
st.pop();
}
tmp.op = s[i];
st.push(tmp); //最后不要忘了把当前操作符压入栈中去
i ++;
}
}
//最后结束将栈中的所有操作符都输出
while(st.size())
{
q.push(st.top());
st.pop();
}
}
/* 后缀表达式求值,利用一个栈来维护值
* 1. 把位于 q 中的后缀表达式,从队头到队尾逐个取出,压入到 sa 栈中去
* 2. 如果当前向 sa 中压入的是操作符 x,则把此时把 sa 中栈顶前两个元素a、b 取出来 进行 axb 操作
* 2. 如果当前项 sa 中压入的事操作数,则报该操作数压入 sa 栈中
*/
double cal()
{
double a, b;
while(q.size())
{
Node cur = q.front(); q.pop();
if(cur.flag)
{
sa.push(cur);
}
else
{
b = sa.top().num;
sa.pop(); //弹出第二操作数
a = sa.top().num;
sa.pop(); //弹出第一操作数
Node tmp;
tmp.flag = 1;
if(cur.op == '+')
{
tmp.num = a + b;
}
else if(cur.op == '-')
{
tmp.num = a - b;
}
else if(cur.op == '*')
{
tmp.num = a * b;
}
else if(cur.op == '/')
{
tmp.num = a / b;
}
sa.push(tmp); //最后把计算的结果重新压入 sa 栈中去
}
}
return sa.top().num;
}
bool check(string s)
{
if((int)s.size() - 1 == 1) return ! p[s[0]];
for(int i = 2; i < s.size() - 1; i ++)
if(p[s[i]] && p[s[i - 1]]) return 0;
int num = 0;
for(int i = 0; i < s.size() - 1; i ++)
{
if(s[i] == '(') num ++;
if(s[i] == ')') num --;
}
return num == 0;
}
int main()
{
init();
string s;
cin >> s;
if(! check(s))
{
cout << "NO" << endl;
return 0;
}
change(s);
cout << cal();
return 0;
}