浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html
题目传送门:https://www.luogu.org/problemnew/show/P1175
中缀表达式转后缀表达式之后直接模拟即可。平常我们所用的都是中缀表达式,后缀表达式题面已经说的很清楚了。
至于怎么转?按照一下几条规则用单调栈维护运算符模拟即可:
1、如果当前位是数字,则直接输出
2、如果当前位是左括号,则直接丢栈然后不管
3、如果当前位是运算符,把栈顶优先度不小于当前运算符的全部弹出然后输出,当前运算符入栈
4、如果是右括号,一直弹栈输出直到与之匹配的左括号出栈
优先级:括号>乘方>乘除>加减
时间复杂度:(O(len^2))
空间复杂度:(O(len))
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
#define ff first
#define ss second
const int maxn=105;
int n1,n2,top,cnt;
char s[maxn],stk[maxn];
pii s1[maxn],s2[maxn];
int quick(int a,int b) {
int res=1;
while(b) {
if(b&1)res=res*a;
a=a*a,b>>=1;
}
return res;
}
int main() {
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++) {
if(s[i]>='0'&&s[i]<='9')s1[++n1]=make_pair(s[i]-'0',1);
if(s[i]=='(')stk[++top]=s[i];
if(s[i]=='+'||s[i]=='-') {
if(i==1||s[i-1]=='(') {
if(s[i]=='+')s1[++n1]=make_pair(s[i+1]-'0',1);
else s1[++n1]=make_pair(-(s[i+1]-'0'),1);
i++;
}
else {
while(top&&stk[top]!='(')
s1[++n1]=make_pair(stk[top],0),top--;
stk[++top]=s[i];cnt++;
}
}
if(s[i]=='*'||s[i]=='/') {
while(top&&stk[top]!='('&&stk[top]!='+'&&stk[top]!='-')
s1[++n1]=make_pair(stk[top],0),top--;
stk[++top]=s[i];cnt++;
}
if(s[i]=='^') {
while(top&&stk[top]!='('&&stk[top]=='^')
s1[++n1]=make_pair(stk[top],0),top--;
stk[++top]=s[i];cnt++;
}
if(s[i]==')') {
while(stk[top]!='(')
s1[++n1]=make_pair(stk[top],0),top--;
top--;
}
}
while(top)s1[++n1]=make_pair(stk[top],0),top--;
pii *a=s1,*b=s2;
while(~cnt) {
for(int i=1;i<=n1;i++)
if(!a[i].ss)printf("%c ",a[i].ff);
else printf("%d ",a[i].ff);
puts("");cnt--;
bool bo=0;n2=0;
for(int i=1;i<=n1;i++) {
if(!bo&&!a[i].ss) {
int num1=b[n2-1].ff,num2=b[n2].ff;
if(a[i].ff=='+')num1+=num2;
if(a[i].ff=='-')num1-=num2;
if(a[i].ff=='*')num1*=num2;
if(a[i].ff=='/')num1/=num2;
if(a[i].ff=='^')num1=quick(num1,num2);
bo=1,n2--;b[n2]=make_pair(num1,1);
}
else b[++n2]=a[i];
}
swap(a,b),swap(n1,n2);
}
return 0;
}