中缀表达式转为后缀表达式需要用到栈
后缀表达式再求值也要用到栈
1.中缀&后缀表达式
2.后缀表达式求值
2.1需要用到栈的结构:
- 从左往右读表达式,读到运算量就入栈,
- 读到运算符的话,就从栈中弹出前面刚刚读过的两个运算量参与运算,结果是一个新的运算量,将他压入栈中。
- 处理完整个后缀表达式之后,栈顶元素就是结果值
2.2举例
过程详述(拿纸自己跟着画一下):
- 从左向右读,读到6入栈,读到2入栈
- 读到 /,把6和2取出来,进行6/2,得到3入栈,(现在栈里面有一个3)
- 继续读,又读到3,3入栈(现在栈里面有2个3)
- 读到 -,那么3-3=0,0入栈
- 读到4,4入栈,读到2,2入栈(现在栈里面有0,4,2)
- 读到* ,取出4,2,进行4*2=8,8入栈(现在栈里面有0,8)
- 读到 +,取出0,8,0+8=8,8入栈
- 结束,栈里面只有一个元素,8,就是最终答案
3.代码展示
首先给你一个中缀表达式,
3.1先转化为后缀表达式
我们用transplate函数实现此功能,有详细注释
记住str2中各个量之间是要有空格的,可以思考:中缀表达式中数字之间是有符号的:19+5意思就很明确,但是后缀表达式中195+什么意思呢,是19+5还是1+95呢,对吧,所以str2存储的时候应该是19 5 +,中间有空格!
详细步骤如下:
- 循环遍历str1
- 遇到数字就直接写到str2里面
- 遇到运算符号就比较它和栈顶元素的优先级高低(symcmp),决定是否入栈
#include<stdio.h>
#define MAXSIZE 100
int symcmp(char a,char b)
{
if(b=='(')
return 1;
else if((b=='*'||b=='/')&&(a=='-'||a=='('||a=='+'))
return 1;
else if((b=='+'||b=='-')&&(a=='('))
return 1;
else
return 0;
}
void transplant(char *str1,char *str2)
{//str1是中缀表达式,str2是目标生成的后缀表达式
char stack[MAXSIZE];//数组模拟栈
int top=-1;
int j=0;
for(int i=0;str1[i]!='\0';i++)//开始遍历str
{
if(str1[i]>='0'&&str1[i]<='9')
str2[j++]=str1[i];//如果是0到9之间的数字,就直接赋值给str2
else
{//遇到各种符号了
if(i!=0&&str2[j-1]!=' ')
str2[j++]=' ';//需要加上一个空格做分割
if(str1[i]==')')//一直输出,直到(出栈,但是不输出
{
while(stack[top]!='(')
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
top--;//相当于(出去了
}
else if(symcmp(stack[top],str1[i])==0)//str1[i]运算符优先级低或相等,则stack出栈
{
while(top>-1&&(symcmp(stack[top],str1[i])==0))//要么栈为空、要么str[i]优先级为高,则停止出栈
//也就是说,要是你一直满足str1[i]运算符优先级低或相等,那你就一直出栈吧
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
stack[++top]=str1[i];//该出栈的都出去了,把str[i]放进来
}
else//str1[i]运算符优先级高,或者等于‘(’,则str[i]入栈
{
stack[++top]=str1[i];
}
}
}
if(str2[j-1]!=' ')
str2[j++]=' ';
while(top>-1)//栈里边还剩下的符号都出来吧!
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
str2[j-1]='\0';//以'\0'结尾
printf("%s",str2);
}
3.2后缀表达式求值(用到栈结构)
int cal(char *str)
{
int stack[MAXSIZE];
int top=-1,tmp=0,k=10;
for(int i=0;str[i]!='\0';i++)
{
if(str[i]>='0'&&str[i]<='9')
{
tmp=tmp*10+str[i]-'0';
}
else if(str[i]==' ')
{
stack[++top]=tmp;
tmp=0;
}
else
{
switch(str[i])
{
case '+':tmp=stack[top-1]+stack[top];break;
case '-':tmp=stack[top-1]-stack[top];break;
case '*':tmp=stack[top-1]*stack[top];break;
case '/':tmp=stack[top-1]/stack[top];break;
}
top-=2;
}
}
stack[++top]=tmp;
return stack[0];
}
4.总体代码:可复制直接运行,已设好初始用例!
#include<stdio.h>
#define MAXSIZE 100
int symcmp(char a,char b)
{
if(b=='(')
return 1;
else if((b=='*'||b=='/')&&(a=='-'||a=='('||a=='+'))
return 1;
else if((b=='+'||b=='-')&&(a=='('))
return 1;
else
return 0;
}
void transplant(char *str1,char *str2)
{//str1是中缀表达式,str2是目标生成的后缀表达式
char stack[MAXSIZE];//数组模拟栈
int top=-1;
int j=0;
for(int i=0;str1[i]!='\0';i++)//开始遍历str
{
if(str1[i]>='0'&&str1[i]<='9')
str2[j++]=str1[i];//如果是0到9之间的数字,就直接赋值给str2
else
{//遇到各种符号了
if(i!=0&&str2[j-1]!=' ')
str2[j++]=' ';//需要加上一个空格做分割
if(str1[i]==')')//一直输出,直到(出栈,但是不输出
{
while(stack[top]!='(')
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
top--;//相当于(出去了
}
else if(symcmp(stack[top],str1[i])==0)//str1[i]运算符优先级低或相等,则stack出栈
{
while(top>-1&&(symcmp(stack[top],str1[i])==0))//要么栈为空、要么str[i]优先级为高,则停止出栈
//也就是说,要是你一直满足str1[i]运算符优先级低或相等,那你就一直出栈吧
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
stack[++top]=str1[i];//该出栈的都出去了,把str[i]放进来
}
else//str1[i]运算符优先级高,或者等于‘(’,则str[i]入栈
{
stack[++top]=str1[i];
}
}
}
if(str2[j-1]!=' ')
str2[j++]=' ';
while(top>-1)//栈里边还剩下的符号都出来吧!
{
str2[j++]=stack[top--];
str2[j++]=' ';
}
str2[j-1]='\0';//以'\0'结尾
printf("%s",str2);
}
int cal(char *str)
{
int stack[MAXSIZE];
int top=-1,tmp=0,k=10;
for(int i=0;str[i]!='\0';i++)
{
if(str[i]>='0'&&str[i]<='9')
{
tmp=tmp*10+str[i]-'0';
}
else if(str[i]==' ')
{
stack[++top]=tmp;
tmp=0;
}
else
{
switch(str[i])
{
case '+':tmp=stack[top-1]+stack[top];break;
case '-':tmp=stack[top-1]-stack[top];break;
case '*':tmp=stack[top-1]*stack[top];break;
case '/':tmp=stack[top-1]/stack[top];break;
}
top-=2;
}
}
stack[++top]=tmp;
return stack[0];
}
int main()
{
char *str = "50+7*2*(2+1-1-1)-3";
char s[MAXSIZE];
transplant(str,s);
int res=cal(s);
printf("\n%d",res);
return 0;
}