表达式求值---(中缀表达式转后缀表达式及后缀表达式求值结合)

题目:
利用栈编写表达式求值程序:输入含有“ + ”、“ - ”、“ * ”、“ / ”四则运算的表达式,其中负数要用(0 - 正数)表示,并以 = 结束。要求输出表达式的值。

输入格式
第一行:一个算术表达式
输出格式
第一行:算术表达式的值
输入样例
3 * (9 - 7) =
输出样例
6

一、解题思路:

①. 注意栈元素为整型类型。由于表达式的运算符号为字符类型,但依然能够以ASCII码形式储存在栈中,故栈元素可以不用定义为字符类型,而定义为整型类型数据即可,方便从后缀表达式中将字符类型转变为整型类型进行处理,保持了栈元素类型的一致性,方便处理
②. 本代码借用 ‘#’ 分隔数字,故本程序可以处理多位数运算的表达式

步骤一:

中缀表达式:
3 - 10 * ( 9 - 12 ) =

从键盘中输入中缀表达式字符串,创建符号栈operate处理中缀表达式,将其转变为后缀表达式储存在字符串suffix[]中

步骤二:

后缀表达式:
3#10#9#12#-*-

处理后缀表达式字符串:创建数字栈number,遍历后缀表达式,如果是数字,则入栈; 如果是运算符,则出栈两个整型数字a,b,分别作为操作数和被操作数进行运算,把运算结果入栈; 后缀表达式遍历结束后,栈中仅存一个元素即为后缀表达式的运算结果

运算结果:

33

二、代码模块:

①、栈的建立基本函数:

#include<malloc.h> 
#include<stdio.h> 
#include<string.h>

#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量

typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等

struct SqStack
{
	SElemType* base; // 在栈构造之前和销毁之后,base的值为NULL
	SElemType* top; // 栈顶指针
	int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈

Status InitStack(SqStack& S)
{
	// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
	S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S.base) return ERROR;
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return OK;
}

Status Push(SqStack& S, SElemType e)
{
	// 在栈S中插入元素e为新的栈顶元素
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base) return ERROR;
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
	return OK;
}

Status Pop(SqStack& S, SElemType& e)
{
	// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
	if (S.top == S.base) return ERROR;
	e = *--S.top;
	return OK;
}

Status GetTop(SqStack S, SElemType& e)
{
	// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
	if (S.top == S.base) return ERROR;
	e = *(S.top - 1);
	return OK;
}

int StackLength(SqStack S)
{
	// 返回栈S的元素个数
	int i;
	i = S.top - S.base;
	return i;
}

Status StackTraverse(SqStack S)
{
	// 从栈顶到栈底依次输出栈中的每个元素
	SElemType* p = (SElemType*)malloc(sizeof(SElemType));
	p = S.top;
	if (S.top == S.base)printf("The Stack is Empty!");
	else
	{
		printf("The Stack is: ");
		p--;
		while (p >= S.base)
		{
			printf("%d ", *p);
			p--;
		}
	}
	printf("\n");
	return OK;
}

②、结合主函数中的if分支对中缀表达式的字符判断运算符的优先级:

//比较栈顶符号和当前符号的优先级,如果栈顶符号优先级较高,则一直出栈,最后把当前符号入栈;否则,当前符号入栈
int ComparePriority(SElemType stackTop, SElemType cur)
{
	switch (stackTop)
	{
	case '(':
		return 1;
		break;
	case '+':
	case '-':
		if (cur == '*' || cur == '/')
			return 1;
		break;
	default:
		break;
	}
	return 0;
}

③、操作数与被操作数的运算:

//运算函数
int Calculate(SElemType ch, int a, int b)
{
	int result = 0;

	switch (ch)
	{
	case '+':
		result = b + a;
		break;
	case '-':
		result = b - a;
		break;
	case '*':
		result = b * a;
		break;
	case '/':
		result = b / a;
		break;
	default:
		break;
	}
	return result;
}

④、主函数(包括中缀表达式转化为后缀表达式和后缀表达式的求值):


int main()
{
	char s[1000];
	gets_s(s,1000);
	char suffix[1000];
	int index_su = 0;

	/*中缀表达式转化为后缀表达式*/
	
	//初始化符号栈,整型元素栈
	SqStack operate;
	InitStack(operate);

	int i;
	int e;
	for (i = 0; i < strlen(s); i++)
	{
		if (s[i] >= '0' && s[i] <= '9')//是数字,保存到后缀表达式中
		{
			suffix[index_su++] = s[i];
			if (s[i + 1] < '0' || s[i + 1] > '9')
			{
				suffix[index_su++] = '#';
			}
		}
		else if (s[i] == ' ' || s[i] == '=')//是空格或等号,忽略
		{
			continue;
		}
		else//是运算符号,需要入栈出栈判断处理
		{
			SElemType top;
			GetTop(operate, top);
			if (StackLength(operate) == 0 || s[i] == '(')//如果栈为空,或者当前符号为左括号,则入栈
			{
				Push(operate, s[i]);
			}
			else if (s[i] == ')')//如果当前符号是右括号,则一直出栈
			{
				do
				{
					Pop(operate, e);
					if (e != '(')
					{
						suffix[index_su++] = e;
					}
				} while (e != '(');
			}
			else if (ComparePriority(top, s[i]) == 1)//当前符号优先级较高
			{
				Push(operate, s[i]);
			}
			else if (ComparePriority(top, s[i]) == 0)//栈顶符号优先级较高
			{
				do
				{
					Pop(operate, e);
					suffix[index_su++] = e;
					GetTop(operate, top);//重新获取栈顶符号
				} while (ComparePriority(top, s[i]) == 0 && StackLength(operate) != 0);//当栈中还有符号并且栈顶符号优先级较高时,出栈
				Push(operate, s[i]);//当前符号入栈
			}
		}
	}

	//把栈中元素全部出栈,保存到后缀表达式中
	do
	{
		Pop(operate, e);
		suffix[index_su++] = e;
	} while (operate.top > operate.base);

	suffix[index_su] = '\0';//结束后缀表达式
	puts(suffix);


	/*后缀表达式求值*/

	//初始化数栈
	SqStack number;
	InitStack(number);

	int num = 0;
	for (i = 0; i < strlen(suffix); i++)
	{
		if (suffix[i] >= '0' && suffix[i] <= '9')
		{
			while (suffix[i] != '#')
			{
				num = num * 10 + (suffix[i++] - '0');
			}
			Push(number, num);
			//printf("num = %d\n", num);
			num = 0;
		}
		else
		{
			int a, b;
			Pop(number, a);
			Pop(number, b);
			int result = Calculate(suffix[i], a, b);
			//printf("a = %d, b = %d, result = %d\n", a, b, result);
			Push(number, result);
		}
	}
	int result;
	Pop(number, result);
	printf("%d\n", result);

	return 0;
}

有任何问题可以留言交流,我一定及时回复

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值