表达式有三种表示方法,分别为:
前缀表示(波兰式):运算符+操作数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优先级顺序出栈,输出。
输入表达式,求其波兰式和逆波兰式。
#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;
}