这道题是我出的,也是很坑的。
【题意】
用程序实现前缀表达式、中缀表达式、后缀表达式的相互转化。
用1、2、3分别表示前缀表达式、中缀表达式、后缀表达式。
输入表达式可能会出现一连串数字,但请把他们看成多个一位数,即123表示1 2 3,以降低大家编码的复杂程度。
输出表达式也不用在中间加空格。
数字均在1~9范围内,且运算符只有+ - * / ^ 5种。(^为幂运算符,幂运算的优先级高于加减乘除)
特殊的,输出的是中缀表达式时,中缀表达式不允许有多余的括号,只有必须时才能加括号,以保证输出的中缀
表达式的运算顺序与输入的前缀表达式或后缀表达式运算顺序相同。
问题只需4个操作:把中缀表达式转成前缀表达式、后缀表达式,把前缀表达式、后缀表达式转成中缀表达式。
1、2问题是类似的。
将中缀表达式转换为前缀表达式:
遵循以下步骤:
(1) 初始化两个栈:运算符栈ops和储存中间结果的栈p;
(2) 从右至左扫描中缀表达式;
(3) 遇到操作数时,将其压入p;
(4) 遇到运算符时,比较其与ops栈顶运算符的优先级,若ops栈顶符号的优先级高于当前符号的,就把它弹入p。
(5) 遇到括号时:
(5-1) 如果是右括号“)”,则直接压入ops;
(5-2) 如果是左括号“(”,则依次弹出ops栈顶的运算符,并压入p,直到遇到右括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最左边;
(7) 将ops中剩余的运算符依次弹出并压入p;
(8) 依次弹出p中的元素并输出,结果即为中缀表达式对应的前缀表达式。
例如,将中缀表达式“1+((2+3)×4)-5”转换成前缀表达式"- + 1 × + 2 3 4 5"
将中缀表达式转换成后缀表达式,与上面类似。
不同之处:p为字符串数组;从左往右扫;遇到运算符时,比较其与ops栈顶运算符的优先级,若ops栈顶符号的优先级不低于当前符号的,就把它加入p;p为答案。
3、4问题是难点。为了优化,还需要写邻接表。
将前缀表达式转换成中缀表达式:
1.用一个栈in存中缀表达式。
2.从右往左扫描。
3.若当前元素为数字,则把它入栈。
4.若为运算符,则需注意优先级。
5.重复3-4,直到扫完。
将后缀表达式转换成中缀表达式,除了从左往右扫描,大体上没有与上面的不同之处。
代码:
STL版
//前缀、中缀、后缀表达式之间的转换。
//这是一道数据结构题,考察邻接表和栈。
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=40010;
int grade(char op)//优先级。用于中缀转前后缀
{
switch(op){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
case 0:
return 4;
}
return 0;
}
void to_postfix(char s[])
{
stack<char>ops;//符号和后缀表达式
vector<char>p;
int n=strlen(s);
for(int i=0;i<n;i++)
{
char c=s[i];
if('0'<=c&&c<='9')p.push_back(c);
else
{
if(c=='(')ops.push(c);
else if(c==')')
{
while(ops.size()&&(c=ops.top())!='(')
{
p.push_back(c);
ops.pop();
}
ops.pop();
}
else
{
while(ops.size()&&grade(ops.top())>=grade(c))
{
p.push_back(ops.top());
ops.pop();
}
ops.push(c);
}
}
}
while(ops.size())p.push_back(ops.top()),ops.pop();
n=0;
for(vector<char>::iterator i=p.begin();i<p.end();i++)
s[n++]=*i;
s[n]=0;
}
void to_prefix(char s[])
{
stack<char>ops,p;
int n=strlen(s);
for(int i=n-1;i>=0;i--)
{
char c=s[i];
if('0'<=c&&c<='9')p.push(c);
else
{
if(c==')')ops.push(c);
else if(c=='(')
{
while(ops.size()&&(c=ops.top())!=')')
{
p.push(c);
ops.pop();
}
ops.pop();
}
else
{
while(ops.size()&&grade(ops.top())>grade(c))
{
p.push(ops.top());
ops.pop();
}
ops.push(c);
}
}
}
while(ops.size())p.push(ops.top()),ops.pop();
n=0;
while(p.size())
s[n++]=p.top(),p.pop();
s[n]=0;
}
struct node//单个字符的存储。目标——用邻接表存字符串。
{
char c;
int r;
node(){r=0;}
}a[N];int tot;
struct segment
{
int l,r;//左右指针。
char op;//最后一个操作符。
segment(){op=0;}
};
void add(segment &x)//加括号。
{
a[++tot].c='(';
a[tot].r=x.l;
x.l=tot;
a[++tot].c=')';
a[x.r].r=tot;
x.r=tot;
}
void con(segment &x,char op,segment y)//connect
{
a[++tot].c=op;
a[x.r].r=tot;
a[tot].r=y.l;
x.r=y.r;
x.op=op;
}
void from_postfix(char s[])
{
stack<segment>in;//infix
tot=0;
int n=strlen(s);
for(int i=0;i<n;i++)
{
char c=s[i];
if('0'<=c&&c<='9')
{
a[++tot].c=c;
segment now;
now.l=now.r=tot;
in.push(now);
}
else
{
segment b=in.top();in.pop();
segment a=in.top();in.pop();
int l,r,m=grade(c);
r=grade(b.op);
l=grade(a.op);
if(l<m)add(a);
if(m>=r)add(b);
con(a,c,b);
in.push(a);
}
}
n=0;
for(int i=in.top().l; i ;i=a[i].r)
s[n++]=a[i].c;
s[n]=0;
}
void from_prefix(char s[])
{
stack<segment>in;//infix
tot=0;
int n=strlen(s);
for(int i=n-1;i>=0;i--)
{
char c=s[i];
if('0'<=c&&c<='9')
{
a[++tot].c=c;
segment now;
now.l=now.r=tot;
in.push(now);
}
else
{
segment a=in.top();in.pop();
segment b=in.top();in.pop();
int l,r,m=grade(c);
l=grade(a.op);
r=grade(b.op);
if(l<m)add(a);
if(m>=r)add(b);
con(a,c,b);
in.push(a);
}
}
n=0;
for(int i=in.top().l; i ;i=a[i].r)
s[n++]=a[i].c;
s[n]=0;
}
char s[N];
int main()
{
int a,b;scanf("%d%d",&a,&b);
scanf("%s",s);
if(a==1)from_prefix(s);
else if(a==3)from_postfix(s);
if(b==1)to_prefix(s);
else if(b==3)to_postfix(s);
printf("%s",s);
return 0;
}
朴素版
//前缀、中缀、后缀表达式之间的转换。
//这是一道数据结构题,考察邻接表和栈。 #include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+100;
int grade(char op)//优先级。用于中缀转前后缀
{
switch(op){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
case 0:
return 4;
}
return 0;
}
void to_postfix(char s[])
{
char ops[N],p[N];int opl=0,pl=0;//符号和后缀表达式
memset(p,0,sizeof(p));
int n=strlen(s);
for(int i=0;i<n;i++)
{
char c=s[i];
if('0'<=c&&c<='9')p[++pl]=c;
else
{
if(c=='(')ops[++opl]=c;
else if(c==')')
{
while(opl>0&&ops[opl]!='(')
{
p[++pl]=ops[opl--];
}
--opl;
}
else
{
while(opl>0&&grade(ops[opl])>=grade(c))
{
p[++pl]=ops[opl--];
}
ops[++opl]=c;
}
}
}
while(opl>0)p[++pl]=ops[opl--];
p[++pl]=0;
for(int i=0;i<pl;i++)s[i]=p[i+1];
}
void to_prefix(char s[])
{
char ops[N],p[N];int opl=0,pl=0;//符号栈和前缀表达式
memset(p,0,sizeof(p));
int n=strlen(s);
for(int i=n-1;i>=0;i--)
{
char c=s[i];
if('0'<=c&&c<='9')p[++pl]=c;
else
{
if(c==')')ops[++opl]=c;
else if(c=='(')
{
while(opl&&ops[opl]!=')')
{
p[++pl]=ops[opl--];
}
--opl;
}
else
{
while(opl&&grade(ops[opl])>grade(c))
{
p[++pl]=ops[opl--];
}
ops[++opl]=c;
}
}
}
while(opl>0)p[++pl]=ops[opl--];
for(int i=0,j=pl;i<pl;i++,j--)s[i]=p[j];
s[pl]=0;
}
struct node//单个字符的存储。目标——用邻接表存字符串。
{
char c;
int r;
node(){r=0;}
}a[N];int tot;
struct segment
{
int l,r;//左右指针。
char op;//最后一个操作符。
segment(){op=0;}
};
void add(segment &x)//加括号。
{
a[++tot].c='(';
a[tot].r=x.l;
x.l=tot;
a[++tot].c=')';
a[tot].r=0;
a[x.r].r=tot;
x.r=tot;
}
void con(segment &x,char op,segment y)//connect
{
a[++tot].c=op;
a[x.r].r=tot;
a[tot].r=y.l;
x.r=y.r;
x.op=op;
}
void from_postfix(char s[])
{
segment in[N>>1];int top=0;//infix
tot=0;
int n=strlen(s);
for(int i=0;i<n;i++)
{
char c=s[i];
if('0'<=c&&c<='9')
{
a[++tot].c=c;
top++;
in[top].l=in[top].r=tot;
in[top].op=0;
}
else
{
segment b=in[top--];
segment &a=in[top];
int l,r,m=grade(c);
r=grade(b.op);
l=grade(a.op);
if(l<m)add(a);
if(m>=r)add(b);
con(a,c,b);
}
}
memset(s,0,N);
int i,j;
for(i=in[top].l,j=0;i ;i=a[i].r,j++)s[j]=a[i].c;
}
void from_prefix(char s[])
{
segment in[N>>1];int top=0;//infix
tot=0;
int n=strlen(s);
for(int i=n-1;i>=0;i--)
{
char c=s[i];
if('0'<=c&&c<='9')
{
a[++tot].c=c;
++top;
in[top].l=in[top].r=tot;
in[top].op=0;
}
else
{
segment a=in[top--];
segment b=in[top];
int l,r,m=grade(c);
r=grade(b.op);
l=grade(a.op);
if(l<m)add(a);
if(m>=r)add(b);
con(a,c,b);
in[top]=a;
}
}
memset(s,0,N);
int i,j;
for(i=in[top].l,j=0;i ;i=a[i].r,j++)
s[j]=a[i].c;
}
char s[N];
int main()
{
int a,b;scanf("%d%d",&a,&b);
scanf("%s",s);
if(a==1)from_prefix(s);
else if(a==3)from_postfix(s);
if(b==1)to_prefix(s);
else if(b==3)to_postfix(s);
printf("%s",s);
return 0;
}