栈应用逆波兰表达式

逆波兰表达式

逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。下面是一些例子:

正常的表达式   逆波兰表达式
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
a=1+3 ---> a,1,3,+,=

代码如下:

typedef enum {
 NUMBER,OPERATOR
}Type;
typedef enum {
 ADD,SUB,MUL,DIV,NOUSED
}OP;
typedef  struct {
 int type;//0表示数字,1表示运算符
 int number;//操作数
 OP operator;//操作符
}Item;
Item array[] = {
 {
  NUMBER,178,NOUSED
 },
 {
  NUMBER,136,NOUSED
 },
 {
  OPERATOR,-1,ADD 
 }
};

这里开头定义部分可能很难理解,因为在c语言中不好表达。下面我将详细解释以上代码:

我们以Item的结构体为核心展开理解,Item里面包含type,number和operator,type表示区分数字和操作符,所以在上面枚举列出了type的类型只有这两种,operator也是一样的,操作符无非是加减乘除,所以用枚举列出OP的类型是这四种,最后的Item array[]是Item类型的结构体数组,这个不难理解。

void  RPN(Item array[], int size)
{
 Stack Stack;
 StackInit(&Stack);
 //"178 136  + "
  for (int i = 0; i < size; i++)
  {
   int result;
   if (array[i].type == NUMBER)
   {//如果是数字,压栈操作
    StackPush(&Stack,array[i].number);
   }
   if (array[i].type == OPERATOR)
   {//如果是操作符,出两次栈
    int n1 = StackTop(&Stack);
    StackPop(&Stack);
    int n2 = StackTop(&Stack);
    StackPop(&Stack);
    switch (array[i].operator)
    {//再根据操作符类型做相关操作
    case ADD:result = n1 + n2; break;
    case SUB:result = n2 - n1; break;
    case MUL:result = n1 * n2; break;
    case DIV:result = n2 / n1; break;
    }
    StackPush(&Stack, result);//最后把结果压栈
   }
  }
  assert(StackSize == 1);//最后栈中只能有一个元素才是正常的
  printf("%d\n", StackTop(&Stack));
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40550018/article/details/82850506