Input
若干行,每行对应一个中缀表达式
Output
若干行,每行对应一个由中缀表达式转换而来的后缀表达式
Sample Input
X+A*(Y-B)-Z/F
A+B*C+(D*M-N)+(S-T)*Y
A-B*C+(D-E*F)/G
Sample Output
XAYB-*+ZF/-
ABC*+DM*N-+ST-Y*+
ABC*-DEF*-G/+
解题思路:
首先如何实现中缀表达式转换成后缀表达式,方法如下
1.首先划分优先级(运算符优先级可参考课本53页)
2. * 和 / 优先级大于 + 和 - "(" 和 ")"我们这里做特殊处理 设定 #号的优先级最低
3.依次扫描中缀表达式 建立两个栈,Sa 和 Sb。Sb中存放运算符,初始化直接将一个#号压入Sb栈底,方便后续操作
4.操作规则是:
(1)如果遇到操作数 压入Sa
(2)如果是运算符 则与Sb栈顶运算符比较优先级,若优先级高于栈顶运算符,则入栈,若小于等于栈顶运算 符,则栈顶运算符出栈,并且压入Sa,然后继续和栈顶运算符比较,直到高于栈顶运 算符优先级,将其压入Sb.
5.特别的 如果遇到左括号 直接压入Sb.然后继续按照上述规则操作,直到遇到右括号时,右括号不压入,将Sb中左括号后的运算符依次弹出并压入Sa.然后弹出左括号
6.中缀表达式扫描完后,将Sb中剩余的运算符依次弹出并压入Sa.
7. 退栈输出Sa.
以上过程请在草稿纸上自己用样例数据实验一遍,理解更加透彻。
ps:特别注意,因为需要比较各个运算符的优先级 故自定义数据类型ElemType
typedef struct node{
char ch;//元素
int level;//优先级
}ElemType;//数据结构
具体代码及注释如下:
#include<stdio.h>
#include<string.h>
#include<malloc.h>
typedef struct node{
char ch;//元素
int level;//优先级
}ElemType;//数据结构
typedef struct{
ElemType *base;
ElemType *top;
}LinkStack;//栈
int InitStack(LinkStack *L)//初始化
{
//这里只是为了A题 直接申请足够空间 未设置增加空间操作
L->base=(ElemType *)malloc(sizeof(ElemType)*10000);
L->top=L->base;
}
int push(LinkStack *L,ElemType elem)//压栈
{
L->top->ch=elem.ch;
char c=elem.ch;
L->top->level=elem.level;
L->top+=1;
}
int compare(LinkStack *S,ElemType elem)//比较运算符的优先级
{
S->top-=1;
int flag= (S->top->level);//将栈顶运算符优先级赋给flag
S->top+=1;
if( flag >= elem.level)
{
return 1;
}
if( flag < elem.level)
{
return 0;
}
}
int pop(LinkStack *L)//弹栈
{
while(L->base!=L->top)
{
printf("%c",L->base->ch);
L->base+=1;
}
}
int main()
{
char a[1000];
while(gets(a))//输入字符串
{
int l=strlen(a);
ElemType b[1000];
for(int i=0;i<l;i++)//给运算符划分优先等级
{
if(a[i]=='+'||a[i]=='-')
{
b[i].ch=a[i];
b[i].level=1;
}
else if(a[i]=='*'||a[i]=='/')
{
b[i].ch=a[i];
b[i].level=2;
}
else if(a[i]=='('||a[i]==')')
{
b[i].ch=a[i];
b[i].level=-1;
}
else
{
b[i].ch=a[i];
b[i].level=100;//操作数可以不赋优先级
}
}
LinkStack L,S;
InitStack(&L);//存放后缀表达式
InitStack(&S);//存放运算符
ElemType F;
F.ch='#';F.level=-2;//压入#号
push(&S,F);
ElemType r;//用来传递给函数的一个中间变量
for(int i=0;i<l;i++)
{
//若是运算符进行判断
if(b[i].ch=='+'||b[i].ch=='-'||b[i].ch=='*'||b[i].ch=='/'
||b[i].ch=='('||b[i].ch==')'||b[i].ch=='#')
{
if(b[i].ch=='(')//若是左括号 直接压栈
{
push(&S,b[i]);
continue;
}
if(b[i].ch==')')//若是右括号 将运算符弹出 放到操作数栈中
{
S.top-=1;
while(S.top->ch!='(')//直到遇到左括号 结束
{
r.ch=S.top->ch;
push(&L,r);
S.top-=1;
}
continue;
}
while(compare(&S,b[i]))//比较优先级 !
{
S.top-=1; //若a[i]优先级高于栈顶运算符 压栈
r.ch=S.top->ch; // 若不高于 则栈顶元素出栈 入操作数栈
push(&L,r); // 然后继续和前一个比较
} // 直到遇到比a[i]优先级低的 跳出循环
push(&S,b[i]); // a[i]入栈
}
else//操作数直接压入操作数栈
{
push(&L,b[i]);
}
}
//字符串扫描完 将剩余的运算符依次入操作数栈
S.top-=1;
r.ch=S.top->ch;
while(S.top!=S.base)
{
push(&L,r);
S.top-=1;
r.ch=S.top->ch;
}
//退栈输出后缀表达式
pop(&L);
printf("\n");
}
}