中缀表达式求值
written on 2022-07-10
补一下普及组知识点,这次总结一下模板,希望以后能熟练地应用。
对于给定的中缀表达式,首先应将其转化为后缀。大致步骤如下:
-
读入字符串(中缀表达式)。
-
开一个新的 \(\text{int}\) 类型数组,以后一般就用 \(H\) 好了,然后开一个 \(\text{char}\) 类型的栈 \(sta\),存放的是扫描中缀表达式过程中遇到的运算符,包括 \(+,-,\times,\div,(\) 五种,然后规定优先级为 \(\text{乘除}=3,\text{加减}=2,\text{左括号}=1\)。
-
若碰到一个左括号,直接入栈。若碰到一个右括号,栈中运算符依次弹出到 \(H\)(不含左括号),直到与之匹配的左括号。若碰到其他运算符,将所有大于等于它的优先级的都弹出,然后再压入这个运算符。
-
若碰到数字,直接放入 \(H\) 数组。
-
最后将栈中剩下的运算符全部放入 \(H\) 数组。
然后就是后缀表达式求值的事情了,这时只要每次碰上一个运算符,就取出两个栈顶(区分原栈,命名为 \(T\))元素做相应运算然后放回栈顶即可,最后栈中剩下的唯一一个元素也就是答案。
我的代码中的 \(\text{Change}\) 演示的是中缀转后缀的过程。
char a[N];
int Go(char x)
{
if(x=='*') return -1;
if(x=='-') return -2;
if(x=='+') return -3;
}
int level(char x)
{
if(x=='(') return 1;
if(x=='+'||x=='-') return 2;
if(x=='*') return 3;
}
int top,H[N];
char sta[N];
void Change()
{
int len=strlen(a+1),x=0;
for(int i=1;i<=len;i++)
{
if(isdigit(a[i]))
{
x=(x*10+a[i]-'0');
if(!isdigit(a[i+1])) H[++H[0]]=x,x=0;
}
else if(a[i]=='x') H[++H[0]]=-4;
else if(a[i]=='(') sta[++top]=a[i];
else if(a[i]==')')
{
while(top&&sta[top]!='(') H[++H[0]]=Go(sta[top--]);
top--;
}
else
{
while(top&&level(sta[top])>=level(a[i])) H[++H[0]]=Go(sta[top--]);
sta[++top]=a[i];
}
}
while(top) H[++H[0]]=Go(sta[top--]);
// for(int i=1;i<=H[0];i++) printf("%d ",H[i]);
}