zsyzlzy

导航

 

这道题是我出的,也是很坑的。
【题意】
用程序实现前缀表达式、中缀表达式、后缀表达式的相互转化。
用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.若为运算符,则需注意优先级。
"op  A   B","A  op  B"设运算符,栈顶两元素形如"op ~~A ~~~B",则需要变成"A~~op~~ B"。
ABa,b,grade(op)()设A、B最后的操作的运算符分别a,b,grade(op)为返回优先级的函数(大的先操作)
grade(a)<grade(op)A则当grade(a)<grade(op)时,A需要加括号。
grade(op)grade(b)B当grade(op)\le grade(b)时,B需要加括号。
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;
}
posted on 2019-07-04 19:28  zsyzlzy  阅读(166)  评论(0编辑  收藏  举报