逆波兰表达式
逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家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));
}