中缀表达式求值(P1175 表达式的转换)

思路:先中缀表达式转后缀,再对后缀表达式求值。

中缀表达式转后缀:O(n)扫一遍输入的中缀表达式:

1.遇到数:直接输出

2.遇到左括号:左括号直接入栈。

3.遇到运算符号:利用建立的符号栈,栈内总原则为高级运算压在低级运算之上。

4.遇到加、减、乘、除、乘方,按照正常的运算优先级处理(可以看一下P1981 表达式求值)。从栈顶开始,将运算优先级高于或等于待入栈符号的所有符号逐一出栈输出,直到遇到栈内优先级低于入栈符号的符号or左括号为止。

5.遇到右括号:持续进行出栈操作,输出运算符,直至遇到左括号。

扫完后,将符号栈内所有剩余符号出栈输出。这时输出的字符串便为输入的中缀表达式的后缀表达式。然后将后缀表达式直接进行运算即可。

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int MAXN=105;
char charac[MAXN];//charac:中缀转后缀时用的运算符栈 
int totc;
char ss[MAXN];//ss:存储中缀表达式 
int first[MAXN],len;//first:运算符优先级
char last[MAXN];//last:存储后缀表达式  
int ans[MAXN],totl,cnt;//ans:求后缀表达式时存储数字 

int main()
{
	scanf("%s",ss+1);
	len=strlen(ss+1);
	first[40]=first[41]=first[94]=2,first[42]=first[47]=1;//制定优先级(first值大的运算优先级高) 
	for(int i=1;i<=len;i++)
	{
		if('0'<=ss[i]&&ss[i]<='9')	last[++cnt]=ss[i];//遇到数:直接输出
		
		if(ss[i]=='(')	charac[++totc]=ss[i];//遇到左括号:左括号直接入栈。
		
		if(ss[i]=='+'||ss[i]=='-'||ss[i]=='*'||ss[i]=='/'||ss[i]=='^')
		//遇到加、减、乘、除、乘方,按照正常的运算优先级处理。
		//从栈顶开始,将运算优先级高于或等于待入栈符号的所有符号逐一出栈输出,
		//直到遇到栈内优先级低于入栈符号的符号 or 左括号为止。
		//然后将当前运算符压入栈中 
		{
			while(totc>0&&first[(int)charac[totc]]>=first[(int)ss[i]])
			{
				if(charac[totc]=='(')	break;
				last[++cnt]=charac[totc];	totc--;
			}
			charac[++totc]=ss[i];
		}
		
		if(ss[i]==')')
		//遇到右括号:持续进行出栈操作,输出运算符,直至遇到左括号。
		{
			while(charac[totc]!='(')
			{
				last[++cnt]=(int)charac[totc];
				totc--;
			}
			totc--;//左括号只出栈不输出 
		}		
	}
	for(int i=totc;i>=1;i--)	last[++cnt]=charac[i];
	for(int i=1;i<=cnt;i++)	 cout<<last[i]<<" ";
	cout<<'\n';
	
	for(int i=1;i<=cnt;i++)//对后缀表达式求值 
	{
		if('0'<=last[i]&&last[i]<='9')	 ans[++totl]=last[i]-'0';
		if(last[i]<'0'||last[i]>'9')
		{
			if(last[i]=='+')	ans[totl-1]+=ans[totl];
			if(last[i]=='-')	ans[totl-1]-=ans[totl];
			if(last[i]=='*')	ans[totl-1]*=ans[totl];
			if(last[i]=='/')	ans[totl-1]/=ans[totl];
			if(last[i]=='^')
			{
				int temp=ans[totl-1];
				for(int j=1;j<=ans[totl]-1;j++)	 ans[totl-1]*=temp;
			}
			totl--;
			for(int j=1;j<=totl;j++)	cout<<ans[j]<<" ";
			for(int j=i+1;j<=cnt;j++)	 cout<<last[j]<<" ";
			cout<<'\n';	
		}
	}	

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值