题目描述
表达式有三种表示方法,分别为:
前缀表示(波兰式):运算符+操作数1+操作数2
中缀表示:操作数1+运算符+操作数2
后缀表示(逆波兰式):操作数1+操作数2+运算符
例如:a +b * (c -d ) - e/f
波兰式:-+a*b-cd/ef (运算符在操作数的前面,用递归计算波兰式)
中缀式:a+b*c-d-e/f
逆波兰式:abcd-*+ef/ (运算符在操作数的后面,用栈计算逆波兰式)
中缀表示就是原表达式去掉扣号。
根据表达式求波兰式、逆波兰式都是教材第三章表达式求值的思想。
求波兰式,需要操作数栈(注意不是计算结果入栈,有计算式入栈),运算符栈。区别在于从后往前扫描表达式,‘(’ 换成')','('换成‘)’。栈顶运算符优先级>新读入运算符优先级出栈,表3.1中的相同运算符优先级>(从左往右计算)改为<,例如栈顶为‘+‘,新读入的为‘+’,则栈顶优先级<新读入的优先级。
求逆波兰式,只需要运算符栈。操作数直接输出,操作符按表3.1优先级顺序出栈,输出。
输入表达式,求其波兰式和逆波兰式。
输入
测试次数
每组测试数据一行,一个合法表达式
输出
对每组测试数据,输出两行
第一行,表达式的波兰表示
第二行,表达式的逆波兰表示
不同组测试数据间以空行分隔。
样例输入
2 4+2*3-10/5 12+3*5+(2+10)*5
样例输出
- + 4 * 2 3 / 10 5 4 2 3 * + 10 5 / - + + 12 * 3 5 * + 2 10 5 12 3 5 * + 2 10 + 5 * +
提示
#include<iostream> #include<stack> #include<string> #include<sstream> #include<algorithm> using namespace std; #define ok 0 #define error -1 #define opsetsize 7 char PoPrior[7][7]= { '<','<','<','<','>','<','>', '<','<','<','<','>','<','>', '>','>','<','<','>','<','>', '>','>','<','<','>','<','>', '>','>','>','>','>','=','>', '<','<','<','<','=','<','>', '<','<','<','<','<','<','=' }; char Prior[7][7]= { ///运算符间的优先关系,分别是+ - * / ( ) # ///按行看+ - * / ( ) # '>','>','<','<','<','>','>', '>','>','<','<','<','>','>', '>','>','>','>','<','>','>', '>','>','>','>','<','>','>', '<','<','<','<','<','=',' ', '>','>','>','>',' ','>','>', '<','<','<','<','<',' ','=' }; double Operate(double a,char theta,double b) { if(theta=='+') return a+b; else if(theta=='-') return a-b; else if(theta=='*') return a*b; else if(theta=='/') return a/b; return error; } char opset[opsetsize]={'+', '-', '*', '/', '(', ')','#'};///运算符集合 int in(char Test,char *p)///1是运算符,0不是运算符 { ///判断字符Test是否是运算符 for(int j=0;j<opsetsize;j++) { if(Test==p[j]) return 1; } return 0; } char Poprecede(char Aop,char Bop) { ///获取两个运算符之间的优先级,Aop是栈顶,Bop是下一个运算符 int i; for(i=0;i<opsetsize;i++) if(opset[i]==Aop) break; int j; for(j=0;j<opsetsize;j++) if(opset[j]==Bop) break; return PoPrior[i][j]; } char precede(char Aop,char Bop) { ///获取两个运算符之间的优先级,Aop是栈顶,Bop是下一个运算符 int i; for(i=0;i<opsetsize;i++) if(opset[i]==Aop) break; int j; for(j=0;j<opsetsize;j++) if(opset[j]==Bop) break; return Prior[i][j]; } void Poland(string exp) { stack<char>Optr; string Myexp=exp; reverse(Myexp.begin(),Myexp.end()); stack<string>Output; string Tempdata; stringstream ss; string theta; char c; int i=0; Optr.push('#'); c=Myexp[0]; while(c!='#'||Optr.top()!='#') { if(in(c,opset)==0) { Tempdata+=c; c=Myexp[++i];///读取下一个字符 if(in(c,opset)!=0) { ///如果c是运算符,表明前面读入了一个完整的操作数 ss.clear(); if(Tempdata.size()!=0) { reverse(Tempdata.begin(),Tempdata.end()); Output.push(Tempdata); Tempdata.clear(); } } } else { ///是运算符,开始计算 switch(Poprecede(Optr.top(),c)) { case'<':///栈顶的优先级低,即Op1<Op2,压入新的运算符 Optr.push(c); c=Myexp[++i]; break; case'=':///脱括号和脱#号,压入新的运算符 Optr.pop(); c=Myexp[++i]; break; case'>':///退栈,暂时先保留该运算符,用来继续判断 theta=Optr.top(); Optr.pop(); Output.push(theta); break; } } } int tag=0; while(!Output.empty()) { if(tag==0) { cout<<Output.top(); Output.pop(); tag++; } else { cout<<" "<<Output.top(); Output.pop(); tag++; } } cout<<endl; } void rePoland(string Myexp) { stack<char>Optr; string Tempdata; stringstream ss; double data; char theta; char c; int i=0; int tag=0; Optr.push('#'); c=Myexp[0]; while(c!='#'||Optr.top()!='#') { if(in(c,opset)==0) { Tempdata+=c; c=Myexp[++i];///读取下一个字符 if(in(c,opset)!=0) { ///如果c是运算符,表明前面读入了一个完整的操作数 ss.clear(); if(Tempdata.size()!=0) { ss<<Tempdata; ss>>data; if(tag==0) { cout<<data; tag=1; } else { cout<<" "<<data; } Tempdata.clear(); } } } else { ///是运算符,开始计算 switch(precede(Optr.top(),c)) { case'<':///栈顶的优先级低,即Op1<Op2,压入新的运算符 Optr.push(c); c=Myexp[++i]; break; case'=':///脱括号和脱#号,压入新的运算符 Optr.pop(); c=Myexp[++i]; break; case'>':///退栈,暂时先保留该运算符,用来继续判断 theta=Optr.top(); Optr.pop(); cout<<" "<<theta; break; } } } cout<<endl; } int main() { string exp; int T; cin>>T; while(T--) { cin>>exp; string myexp=exp; reverse(myexp.begin(),myexp.end()); myexp+="#"; reverse(myexp.begin(),myexp.end()); Poland(myexp); exp+="#"; rePoland(exp); if(T) cout<<endl; } return 0; }