poj 1400 Complicated Expressions去除多余的括号

来源:互联网 发布:2015年9月非农数据 编辑:程序博客网 时间:2024/05/22 02:17

题目大意: 四则运算,在考虑运算符优先级的情况下,去除多余的括号,然后保证计算后的结果与之前的一样。


解题思路,先转成后缀表达式去除括号,然后通过后缀表达式加必要的括号转成中缀表达式。

 

中缀转后缀:

从左到右扫描中缀表达式,

1.遇到操作数直接存入A.

2.遇到 ( 压入sptr栈

3.遇到+, -, 看sptr栈顶元素,若不为 ( ,则弹出存入A, 而后将当前操作符压入sptr.

4.遇到*, /, 看sptr栈顶的元素,仅仅当栈顶元素为 * 或 / 时 弹栈,存入A,再将遇到的操作符压栈sptr

5,遇到 ), 依次弹出sptr栈顶元素,直到弹出(为止。

若扫描完后,sptr还有元素,则依次弹出存入A.



后缀表达式转中缀表达式。

结果栈为A,操作符栈为sptr

对后缀表达式从后往前扫描

设置一个标志位isLeaf 表示当前处理的操作符是否是左子树,

初始化为false

1.如果当前为操作符


1.1 如果A栈顶操作符(说明在处理二叉树的左子树), 

如果A为空或栈顶不为操作, 符,则将当前操作符压入sptr


1.1如果isLeaf 为true(说明在处理的操作符作为父节点的左子树)

1.1.1如果A不为空且栈顶操作符为*或/, 当前操作符为+或-,则将)压入栈A, 将(压入sptr(为了标识左括号)

最后将当前操作符压入sptr. 然后将isLeaf设置为false,表示左子树的根节点处理完


1.2如果isLeaf 为false(说明在处理的操作符作为父节点的右子树),

如果sptr不为空,则比较当前操作符与sptr栈顶的操作符的优先级。

1.2.1如果sptr栈顶为 - , 若 当前操作符不为 * 和 / 时,将 ) 压入栈 A, 将 ( 压入 sptr

1.2.2如果sptr栈顶为 / , 将 ) 压入栈 A, 将 ( 压入sptr.

1.2.3如果sptr栈顶为 *, 当前操作符为+ 或 - 时, 将 ) 压入栈 A, 将 ( 压入sptr.

最后将当前操作符压入sptr.


2.如果当前为操作数

将操作数压入A.

然后进入如下判断:

2.1如果sptr为空,则结束

2.2如果sptr栈顶为( ,则将(压入A,转2.2继续判断,如果sptr为空结束, 如果不为@转2.3

2.3将sptr栈顶元素弹出,压入A, 将isLeaf设置为true,表示此运算符需要处理它的左子树.


最后将A逐个弹出,就是最终的结果

源码:

#include <cstdio>#include <stack>#include <cstring>using namespace std;const int maxn = 255;char infix[maxn], postfix[maxn];int n;void infix2postfix(char *infix, char *postfix);//中缀转后缀 void postfix2infix(char *infix, char *postfix);//后缀转中缀 int compareOp(char op1, char op2); // 判断操作符优先级 bool isOp(char op); //判断是否为运算符 int main(){int n;scanf("%d", &n);while(n-- != 0){char infix[maxn], postfix[maxn];scanf("%s", infix);infix2postfix(infix, postfix);postfix2infix(infix, postfix);printf("%s\n", infix);}return 0;}int compareOp(char op1, char op2){if(op1 == '*' || op1 == '/'){if(op2 == '*' || op2 == '/')return 0;elsereturn 1;} else{if(op2 == '+' || op2 == '-')return 0;elsereturn -1;}}bool isOp(char op){return op == '-' || op == '+' || op == '*' || op == '/'; } void infix2postfix(char *infix, char *postfix){stack<char> sptr;for(char *letter = infix; *letter != '\0'; letter++) {switch(*letter) {case '(':sptr.push(*letter);break;case '+':case '-':while(!sptr.empty()) {char tmp = sptr.top();if(tmp != '(' ){*postfix++ = tmp;sptr.pop();}elsebreak;}sptr.push(*letter);break;case '*':case '/':while(!sptr.empty()) {char tmp = sptr.top();if(tmp == '*' || tmp == '/'){*postfix++ = tmp;sptr.pop();}elsebreak;}sptr.push(*letter);break;case ')':while(!sptr.empty()) { char tmp = sptr.top(); sptr.pop(); if(tmp != '(')*postfix++ = tmp; else break;}break;default:*postfix++ = *letter;break;}} while(!sptr.empty()) {*postfix++ = sptr.top();sptr.pop(); } *postfix = '\0';} void postfix2infix(char *infix, char *postfix){stack<char>sptr;stack<char>A;int len = strlen(postfix);postfix += (len - 1);       bool isLeft = false;for(int i = 0; i < len; i++, postfix--) {if(isOp(*postfix)){if(isLeft){if(!A.empty() && (A.top() == '*' || A.top() == '/') && (*postfix == '+' || *postfix == '-')){A.push(')');sptr.push('(');}isLeft = false;}else if(!sptr.empty()){if(sptr.top() == '-' && *postfix != '*' && *postfix != '/'|| sptr.top() == '/'|| sptr.top() == '*' && (*postfix == '+' || *postfix == '-')    ){A.push(')');sptr.push('(');} }sptr.push(*postfix);}else{A.push(*postfix);while(!sptr.empty() && sptr.top() == '('){A.push(sptr.top());sptr.pop();}if(!sptr.empty()){A.push(sptr.top());sptr.pop();                          isLeft = true;}}} while(!A.empty()){*infix++ = A.top();A.pop();}*infix = '\0';} 



0 0