用栈实现逆波兰表达式

             什么是逆波兰表达式?我们对于一个算式的表述通常是这样: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;
}

           运行结果:

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值