一 逆波兰表达式描述
逆波兰表达式又叫做后缀表达式。就是将运算符置于运算对象的后面,比如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;
}
四 逆波兰表达式转化及求值结果展示