中缀表达式转后缀表达式
在学习数据结构的时候,我们知道,栈有很多的应用,其中比较常见的一个就是中缀表达式转后缀表达式问题。
中缀表达式转后缀表达式的算法思想:
(1)数字:直接加入后缀表达式
(2)运算符:
A.若为’(’ ,入栈 ;
B.若为’)’,则依次把栈中的运算符加入后缀表达式,直到出现 ‘(’,并从栈中删除’(’;
C.若为’+’,’-’,’*’,’/’ ,则分为以下情况讨论:
a.栈空:入栈;
b.栈顶元素为’(’:入栈;
c.高于栈顶元素优先级:入栈;
d.若不属于以上情况,则依次弹出栈顶运算符,直到一个优先级比它低的运算符或’('为止;
D.遍历完成,若栈非空,依次弹出所有元素。
注意:
该代码以整数式子为例, 可以识别的符号有’(’ ‘)’ ‘+’ ‘-’ ‘*’ ‘/’
- 代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define BASE_SIZE 10
#define UP_SIZE 5
typedef struct stack {
char *base;//栈底指针
char *top;//栈顶指针
int s_size;//栈的长度
} Stack;
int InitStack(Stack *S) {//初始化栈
S->base=(char *)malloc(BASE_SIZE*sizeof(char));
if(!S->base)
return 0;//开辟空间失败
S->top=S->base;
S->s_size=BASE_SIZE;
return 1;//开辟空间成功
}
int Push(Stack *S,char e) {
if(S->top-S->base>=S->s_size) {//栈满,重新分配空间
S->base=(char *)realloc(S->base,(BASE_SIZE+UP_SIZE)*sizeof(char));
if(!S->base) exit(0);
S->top=S->base+S->s_size;
S->s_size=S->s_size+UP_SIZE;
}
*(S->top++)=e;
return 1;
}
char Pop(Stack *S) {
char e;
if(S->top==S->base)
return 0;//栈空
e=*(--S->top);
return e;
}
void Postfix(Stack *S) {
char *p;
char ch;
char outch;
scanf("%c",&ch);
while(ch!='#') {
while(isdigit(ch) ) {
printf("%c",ch);//遇到数字直接加入后缀表达式
scanf("%c",&ch);
}
//+,-
if(ch=='+'||ch=='-') {
if(!(S->top - S->base)) {//在栈空时候入栈
Push(S,ch);
} else {
do {
outch=Pop(S);//outch为栈顶元素
if(outch=='(') {
Push(S,outch);
} else {
printf("%c ",outch);
}
} while( (S->top - S->base) && outch != '(' );
Push(S,ch);
}
}
//遇到右括号,则依次把栈中的运算符加入后缀表达式,直到出现(,并从栈中删除(
else if(ch==')') {
outch= Pop(S);
while(outch!='(') {
printf("%c ",outch);
outch= Pop(S);
}
} else if(ch=='*'||ch=='/'||ch=='(') {
Push(S,ch);
}
else if(ch=='#') {
break;
}
else {
printf("\n输入格式错误!\n");
return ;
}
scanf("%c",&ch);
}
while((S->top - S->base)) {
outch=Pop(S);
printf("%c ",outch);
}
}
int main() {
Stack Sta;
Stack *S=&Sta;
if(InitStack(S))
printf("请输入中缀表达式,以#结尾:\n");
Postfix(S);
return 0;
}
//((4+3)*5+6)/5#
//(4-5*6)/5+6*4#
-
运算结果如下:
-
补充知识
在实现中缀表达式转后缀表达式的时候,后序遍历二叉树也是一个常用的方法。这里面涉及两个知识点:
(1)将表达式转为二叉树;
(2)使用后序遍历算法,得出后序遍历二叉树的序列。