題目描述
表達式有三種表示方法,分別為:
前綴表示(波蘭式):運算符+操作數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; }
