【Openjudge】中缀表达式的值

来源:互联网 发布:小甲鱼c语言教程 编辑:程序博客网 时间:2024/06/06 16:37

队列和栈来回倒腾。

思路是比较典型的思路,现转成逆波兰表达式(运用栈),然后输入到队列,然后计算值(运用栈)。

中缀表达式转化逆波兰(后缀表达式)思路是这样的。

首先,逆波兰表达式的数字顺序是和中缀一样的。于是数字方面我们只需要碰到一个输入到队列一个即可。关键在于,运算符号怎么处理。

容易注意到,我们所需要做的就是调整中缀表达式的运算符的出现顺序,并输出到逆波兰中,使之与中缀表达式的计算顺序一致。如何做到这一点呢?需要运用栈。

首先明白这么几点:

1,在没有括号的情况下,如果两个相邻的操作符是相同的,先出现的一定需要被先计算。eg:a+b+c,第一个加号一定先于第二个运算,但是注意,我们并不知道下一个运算是否是第二个加号。eg:a+b+c*d,显然,第一个+号运算之后,是*号运算,然后才是第二个+号运算。

2,在没有括号的情况下,如果第一个操作符的优先级高于第二个,则,第一个操作符一定被先计算,同样,我们不知道下一个运算是不是第二个操作符。

3,在没有括号的情况下,如果第二个操作符的优先级高于第一个,则,这两个操作符的顺序需要变换(需要运用到栈的地方,后进先出)。

4,右括号,先进行括号内的运算。

这四条明白了,意味着我们知道什么时候需要运用到栈调整运算符的出现顺序。

代码最难的地方就是这个地方了,计算逆波兰表达式,比较简单,碰到数字压栈,碰到符号,弹出栈顶的两个元素,计算结果,将结果压栈,知道全部读入完毕,栈顶即结果。

#include<iostream>#include<stack>#include<queue>#include<string>using namespace std;bool opcmp(char op1, char op2){if (op1 == '+' || op1 == '-'){ if (op2 == '*' || op2 == '/'){return false;}}return true;}int main(){stack<int> ist;stack<char> cst;queue<string> cq;char a[700] = {};int n;char c;cin >> n;while (n --){cin >> a;{for (int i = 0; a[i] != 0; i ++){c = a[i];if (c >= '0' && c <= '9'){string t;while(a[i] >= '0' && a[i] <= '9'){t.push_back(a[i]);i++;}i --;cq.push(t);}else{if (c == '('){cst.push(c);}else if (c == ')'){while (cst.top() != '('){cq.push(string(1,cst.top()));cst.pop();}cst.pop();}else if (cst.empty()){cst.push(c);}else if (opcmp(cst.top(), c)){while (!cst.empty() && cst.top() != '(' && opcmp(cst.top(), c)){cq.push(string(1,cst.top()));cst.pop();}cst.push(c);}else{cst.push(c);}}}}while (!cst.empty()){cq.push(string(1,cst.top()));cst.pop();}int x, y;while (!cq.empty()){string t = cq.front();if (t[0] >= '0' && t[0] <= '9'){ist.push(atoi(t.c_str()));}else{y = ist.top();ist.pop();x = ist.top();ist.pop();switch(t[0]){case '+':ist.push(x + y);break;case '-':ist.push(x - y);break;case '*':ist.push(x * y);break;case '/':ist.push(x / y);break;}}cq.pop();}cout << ist.top();ist.pop();cout << endl;}}

原创粉丝点击