思路:先中缀表达式转后缀,再对后缀表达式求值。
中缀表达式转后缀: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;
}