表达式求值问题

任何一个表达式都是操作数、运算符、界限符组成的,统称他们为单词。一般地,操作数既可以是常数,也可以是被说明为变量常量的标识符,运算符可以被分为算数运算符、关系运算符和逻辑运算符三类,基本界限符左右括号表达式结束符等。为了叙述的简洁,在此仅讨论简单算数表达式的求值问题,这种表达式仅含加减乘数四种运算符。
下面把运算符和界限符统称为算符
我们知道,算数四则运算遵循下面规律:
(1)先乘除后加减
(2)从左到右
(3)先括号内,后括号外
在这里插入图片描述
在这里插入图片描述
【案例实现】
为了实现算符优先算法,可以使用两个栈,一个栈为OPTR,用于寄存运算符,一个栈为OPND,用于寄存操作数或运算结果

【算法步骤】
1.初始化OPTR和OPND两个栈,并将表达式初始符“#”压入OPTR中
2.扫描表达式,读入第一个字符ch,如果表达式没有扫描完毕至“#”或OPTR的栈顶元素不为“#”时,则循环执行以下操作:
(1)若ch不是运算符,则压入OPND中,读入下一字符
(2)若ch是运算符,则根据OPTR的栈顶元素和ch的优先级比较结果,做不同的处理:
[1]若是小于,则ch压入OPTR中,读下一字符
[2]若是大于,则弹出OPTR栈顶的运算符,从OPND栈中弹出两个数,进行响应的运算,结果压人OPND中
[3]若是等于,则OPTR的栈顶元素是"(“且ch是”)",这时弹出OPTR栈顶的“(",相当于括号匹配成功,然后读入下一字符ch
3.OPND栈顶元素即为表达式求值的结果,返回此元素

【算法分析】
在这里插入图片描述
在这里插入图片描述

【算法代码】

char EvaluateExpression()
{
	//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈
	InitStack(OPND);	//初始化OPTR栈
	InitStack(OPTR);	//初始化OPND栈
	push(OPTR,'#');	//将表达式起始符'#'压入栈OPTR中
	cin>>ch;
	while(ch!='#'&&GetTop(OPTR)!='#')	//表达式没有扫描完毕或者OPTR栈顶不为“#”时
	{
		if(!In(ch))			//如果ch不是运算符,入栈,并扫描下一个字符
		{
			push(OPTR,ch);
			cin>>ch;
		}
		else
		{
			switch(Precede(OPTR),ch)	//比较OPTR栈顶元素和ch的优先级
			{
				case '<':
					push(OPTR,ch);
					cin>>ch;
					break;
				case '>':
					//记住,这个地方不用cin,为什么不用具体看上面流程图
					pop(OPTR,theta);
					pop(OPND,b);
					pop(OPND,a);
					push(OPND,operate(a,theta,b));
					break;
				case '=':
					pop(OPTR,x);
					cin>>ch;
					break;
			}
		}
	}
	return GetTop(OPND);	//运算结果最终在OPND的栈顶
}

另外需要特别注意的是,上述算法中的操作数只能是一位数,因为这里使用的是OPND栈是字符栈,如果要进行多位数运算,则需要将OPND改为数栈,读入的数字字符平成数之后再入栈

#include<iostream>
using namespace std;

typedef struct Node
{
   
	char data;
	struct Node *next;
};

typedef struct Stack
{
   
	struct Node *top;
	int size;
};

bool InitStack(Stack *&s)
{
   
	s->top = NULL;
	s->size = 0;
	if (s->top == NULL)
		return true;
	return false;
}

void push(Stack *&s, char ch)
{
   
	Node *newNode = new Node;
	newNode->data = ch;

	newNode->nex
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值