逆波兰表达式(后缀表达式)及其计算

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



四  逆波兰表达式转化及求值结果展示

逆波兰表达式(后缀表达式)及其计算_第1张图片

 

 

 

 


    

你可能感兴趣的:(逆波兰表达式(后缀表达式)及其计算)