什么是逆波兰表达式?我们对于一个算式的表述通常是这样:X+Y,即:"操作数1 操作符 操作数2”。而逆波兰表达式刚好统一,先操作数,后操作符,这就是逆波兰表达式。看下图就很好理解:
用栈实现逆波兰表达式,是一个很经典的例子。本文中我将主要叙述如何用栈实现逆波兰表达式的思路和过程,不在此叙述有关栈的定义和操作相关问题,具体的可以参考《栈的定义以及用栈实现逆波兰表达式》这篇文章中有关栈的定义。
我的基本思路是由于操作数在操作符前面,所以按顺序遍历整个表达式,遇到操作数的时候进栈,遇到操作符的时候让操作数出栈并运算。然后将他们的结果进站即可。
具体的实现过程可分为以下两个步骤:
1.实现运算过程中各种元素的定义:
(1)首先定义存放逆波兰表达式的数组类型Item的结构体。Item结构体中包括Type类型元素type,int类型的number(操作数)和OP类型的operator(操作符)。
(2)Type是一个定义为包含NUMBER和OPERATOR的枚举类型。每当循环遍历到每个Item类型的数组元素时,应首先判断每个数组元素结构体中第一个成员type的类型,如果type时是NUMBER则直接选择结构体中的操作数参与运算,否则选择操作符参与运算。
(3)元素OP是一个包含ADD, SUB, MUL, DIV, NOUSE的运算符号的枚举类型。
相关代码如下:
typedef enum{
NUMBER,
OPERATOR
}Type;
typedef enum{
ADD, SUB, MUL, DIV, NOUSE
}OP;
typedef struct{
Type type;
int number;
OP operator;
}Item;
2.运算的具体过程:
(1)定义一个Item类型的数组array来存放逆波兰表达式,定义一个栈stack来存放操作数。
(2)从数组array第一个元素开始,依次向后循环遍历整个数组。
(3)如果数组元素是操作数时,直接压入栈stack内。如果数组元素是操作符时,依次从栈stack内弹出两个操作数进行操作符运算,将运算结果再次压入栈内,然后依次向后遍历数组,重复步骤(3)过程,直到数组遍历完为止。
(4)数组遍历完,栈stack内只剩一个操作数时,那就是最终的运算结果,弹出然后打印即可。
相关代码如下:
void RPN(Item array[], int size)
{
Stack stack;
StackInit(&stack);
for (int i = 0; i < size; i++)
{
if (array[i].type == NUMBER)
{
StackPush(&stack, array[i].number);
}
else
{
int n1 = StackTop(&stack);
StackPop(&stack);
int n2 = StackTop(&stack);
StackPop(&stack);
int result;
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;
}
StackPush(&stack, result);
}
}
assert(StackSize(&stack) == 1);
printf("%d\n", StackTop(&stack));
}
我的测试数组和测试代码定义如下:
//测试数组
Item array[] = {
{
NUMBER,
178,
NOUSE
},
{
NUMBER,
176,
NOUSE
},
{
OPERATOR,
-1,
ADD
}
}
//测试代码
void test()
{
int size = sizeof(array) / sizeof(array[0]);
RPN(array,size);
}
int main()
{
test();
system("pause");
return 0;
}
运行结果: