一 逆波兰表达式描述
逆波兰表达式又叫做后缀表达式。就是将运算符置于运算对象的后面,比如a+b表示为ab+,a+(b-c)*d ---> a,b,c,-,d,*,+
二 逆波兰表达式转化及求值分析
初始化一个栈,再用两个字符数组,一个数组专门用来逐个读取字符,当遇到数字的时候存入另外一个字符数组,并以空格隔开,当读入运算符时,通过专门的调运函数优先级判断,进行出栈入栈的操作.当字符数组遍历完之后,判断栈是否为空,如果为空的话,将剩下的依次读入。
逆波兰表达式求值,将其字符数组传进来,还是逐个读取字符,逐个判断,这个思路和逆波兰表达式转化有点相似,做的时候特别要注意s.top的值,我做的时候在s.top费了很多事,于是我先让s.top初始化为-1,后续处理就比较简单了.
三 代码
#include<stdio.h> #include<string.h> #include<malloc.h> #include<stdlib.h> #define maxsize 50 typedef struct // 处理逆波兰表达式实现计算 { int data[maxsize]; int top; }Opstack; typedef struct // 处理逆波兰表达式实现 { char data[maxsize]; int top; }Seqstack; void initstack(Seqstack *s) // 初始化栈 { s->top=0; } int emptystack(Seqstack s) //判断是否为空栈 { if(s.top==0) { return 1; } else { return 0; } } int pushstack(Seqstack *s,char e) // 进栈 { if(s->top>=maxsize) { printf("栈已满,不能进栈!\n"); return 0; } else { s->data[s->top]=e; s->top++; return 1; } } int popstack(Seqstack *s,char *e) // 出栈 { if(s->top==0) { printf("栈已空\n"); return 0; } else { s->top--; *e=s->data[s->top]; return 1; } } int Gettop(Seqstack s,char *e) // 读出栈顶元素 { if(s.top<=0) { printf("栈已空\n"); return 0; } else { *e=s.data[s.top-1]; return 1; } } int pre(char c) // 判断优先级 { int i; switch(c) { case '(':i=0;break; case '+':i=1;break; case '-':i=1;break; case '*':i=2;break; case '/':i=2;break; case ')':i=3;break; } return i; } void nibolan(char str[],char exp[]) //逆波兰表达式实现 { Seqstack s; char ch,e; int i=0,j=0; initstack(&s); // 初始化栈 ch=str[i]; while(ch!='\0') // 依次读取ch { switch(ch) { case'(': pushstack(&s,ch); break; case')': popstack(&s,&e); while(e!='(') { exp[j++]=e; // ++j; popstack(&s,&e); } break; case'+': case'-': case'*': case'/': if(emptystack(s)) pushstack(&s,ch); else { Gettop(s,&e); if(pre(ch)>pre(e)) pushstack(&s,ch); else { if(pre(ch)<=pre(e)&&!emptystack(s)) { popstack(&s,&e); exp[j]=e; ++j; } pushstack(&s,ch); } } break; case ' ': break; //遇到空格直接跳过 default: while(ch>='0'&&ch<='9')//遇到数字存入字符数组 { exp[j++]=ch; //j++; //i++; ch=str[++i]; } i--; exp[j++]=' ';//自动加空格 //j++; } i++; ch=str[i]; } while(!emptystack(s))//如果栈不为空,将剩下的依次读入字符数组 { popstack(&s,&e); exp[j]=e; j++; } exp[j]='\0'; } int calculatenibolan(char a[]) //计算逆波兰表达式 { Opstack s; int i=0; int x1,x2; int m=1; //m观察哪一步做什么运算 int value; int result; s.top=-1; //s.top初始指向-1 while(a[i]!='\0') { if(a[i]!=' '&&a[i]>='0'&&a[i]<='9')//如果是数字 { value=0; while(a[i]!=' ') // 读出数字 { value=value*10+(a[i]-48); //实现从字符中读出多位数 i++; } s.top++; s.data[s.top]=value; // s.top++; i++; } else { switch(a[i]) { case '+': printf("\n计算加法 %d : ",m++); x1=s.data[s.top]; printf("x1=%d,s.top=%d\n",x1,s.top); s.top--; x2=s.data[s.top]; printf("x2=%d,s.top=%d\n",x2,s.top); s.top--; result=x1+x2; s.top++; s.data[s.top]=result; printf("x1+x2=%d,s.top=%d\n",s.data[s.top],s.top); break; case '-': printf("\n计算减法 %d ",m++); x1=s.data[s.top]; printf("x1=%d,s.top=%d\n",x1,s.top); s.top--; x2=s.data[s.top]; printf("x2=%d,s.top=%d\n",x2,s.top); s.top--; result=x2-x1; s.top++; s.data[s.top]=result; printf("x1-x2=%d\n",result); break; case '*': printf("\n计算乘法 %d",m++); x1=s.data[s.top]; printf("x1=%d,s.top=%d\n",x1,s.top); s.top--; x2=s.data[s.top]; printf("x2=%d,s.top=%d\n",x2,s.top); s.top--; result=x2 * x1; s.top++; s.data[s.top]=result; printf("x1 * x2=%d\n",result); break; case '/': printf("\n计算除法 %d",m++); x1=s.data[s.top]; printf("x1=%d,s.top=%d\n",x1,s.top); s.top--; x2=s.data[s.top]; printf("x2=%d,s.top=%d\n",x2,s.top); s.top--; result=x2/x1; s.top++; s.data[s.top]=result; printf("x1 / x2=%d\n",result); break; case ' ':break; //遇到空格跳过 } i++; } } return result; //返回整数值 } int main(void) //主函数 { char a[maxsize],b[maxsize]; int val; printf("请你输入一个合法的表达式:\n"); gets(a); nibolan(a,b); printf("逆波兰表达式:%s\n",b); val=calculatenibolan(b); printf("\n表达式的计算结果%s=%d\n",a,val); return 0; }
四 逆波兰表达式转化及求值结果展示