使用栈实现表达式求值

使用栈实现表达式求值任何一个表达式都是由操作数,运算符,界限符组成的。操作数即是参加运算的数值或者变量,运算符则是加减乘除等组成,为简单起见,这里只实现加减乘除的运算,而常见的界限符则是左右括号和终止符。在运算过程中,要判断两个先后出现的运算符之间的优先顺序。为了实现算法,设置两个工作栈:用于存储运算符的栈opter,以及用于存储操作数及中间结果的栈opval。算法基本思想如下:(1)首先将操作数栈opv

大家好,又见面了,我是你们的朋友全栈君。

为了实现用栈计算算数表达式的值,需设置两个工作栈:用于存储运算符的栈opter,以及用于存储操作数及中间结果的栈opval。

算法基本思想如下:

(1)首先将操作数栈opval设为空栈,而将’#’作为运算符栈opter的栈底元素,这样的目的是判断表达式是否求值完毕。

(2)依次读入表达式的每个字符,表达式须以’#’结尾,若是操作数则入栈opval,若是运算符,则将此运算符c与opter的栈顶元素top比较优先级后执行相应的操作,(具体操作如下:(i)若top的优先级小于c,即top<c,则将c直接入栈opter,并读入下一字符赋值给c;(ii)若top的优先级等于c,即top=c,则弹出opter的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;(iii)若top优先级高于c,即top>c,则表明可以计算,此时弹出opval的栈顶两个元素,并且弹出opter栈顶的的运算符,计算后将结果放入占opval中。)直至opter的栈顶元素和当前读入的字符均为’#’,此时求值结束。

算符间的优先关系如下表所示:

使用栈实现表达式求值

表中需要注意的是θ1为opter的栈顶元素,θ2位从表达式中读取的操作符,此优先级表可以用二维数组实现,具体见代码(表来源:严蔚敏《数据结构》)。

具体代码如下:

#include<iostream>     //输入的表达式要以'#'结尾,如‘5+6*3/(3-1)#’
#include<cstring>
#include<cstdio>
#include<cctype>
#include<stack>
using namespace std;

stack<char> opter;    //运算符栈
stack<double> opval;  //操作数栈

int getIndex(char theta)   //获取theta所对应的索引
{
	int index = 0;
	switch (theta)
	{
	case '+':
		index = 0;
		break;
	case '-':
		index = 1;
		break;
	case '*':
		index = 2;
		break;
	case '/':
		index = 3;
		break;
	case '(':
		index = 4;
		break;
	case ')':
		index = 5;
		break;
	case '#':
		index = 6;
	default:break;
	}
	return index;
}

char getPriority(char theta1, char theta2)   //获取theta1与theta2之间的优先级
{
	const char priority[][7] =     //算符间的优先级关系
	{
		{ '>','>','<','<','<','>','>' },
		{ '>','>','<','<','<','>','>' },
		{ '>','>','>','>','<','>','>' },
		{ '>','>','>','>','<','>','>' },
		{ '<','<','<','<','<','=','0' },
		{ '>','>','>','>','0','>','>' },
		{ '<','<','<','<','<','0','=' },
	};

	int index1 = getIndex(theta1);
	int index2 = getIndex(theta2);
	return priority[index1][index2];
}

double calculate(double b, char theta, double a)   //计算b theta a
{
	switch (theta)
	{
	case '+':
		return b + a;
	case '-':
		return b - a;
	case '*':
		return b * a;
	case '/':
		return b / a;
	default:
		break;
	}
}

double getAnswer()   //表达式求值
{
	opter.push('#');      //首先将'#'入栈opter
	int counter = 0;      //添加变量counter表示有多少个数字相继入栈,实现多位数的四则运算
	char c = getchar();
	while (c != '#' || opter.top() != '#')   //终止条件
	{
		if (isdigit(c))   //如果c在'0'~'9'之间
		{
			if (counter == 1)   //counter==1表示上一字符也是数字,所以要合并,比如12*12,要算12,而不是单独的1和2
			{
				double t = opval.top();
				opval.pop();
				opval.push(t * 10 + (c - '0'));
				counter = 1;
			}
			else
			{
				opval.push(c - '0');     //将c对应的数值入栈opval
				counter++;
			}
			c = getchar();
		}
		else
		{
			counter = 0;   //counter置零
			switch (getPriority(opter.top(), c))   //获取运算符栈opter栈顶元素与c之间的优先级,用'>','<','='表示
			{
			case '<':               //<则将c入栈opter
				opter.push(c);
				c = getchar();
				break;
			case '=':               //=将opter栈顶元素弹出,用于括号的处理
				opter.pop();
				c = getchar();
				break;
			case '>':               //>则计算
				char theta = opter.top();
				opter.pop();
				double a = opval.top();
				opval.pop();
				double b = opval.top();
				opval.pop();
				opval.push(calculate(b, theta, a));
			}
		}
	}
	return opval.top();   //返回opval栈顶元素的值
}

int main()
{
	//freopen("test.txt", "r", stdin);
	int t;     // 需要计算的表达式的个数
	cin >> t;
	getchar();
	while (t--)
	{
		while (!opter.empty())opter.pop();
		while (!opval.empty())opval.pop();
		double ans = getAnswer();
		cout << ans << endl<< endl;
		getchar();
	}
	return 0;
}

结果:

使用栈实现表达式求值

使用栈实现表达式求值

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148806.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 纯CSS实现表单验证[通俗易懂]

    纯CSS实现表单验证[通俗易懂]纯CSS实现表单验证

    2022年4月21日
    78
  • 启动计算机 gho文件,u盘里只有gho文件怎么重装win7系统图解

    启动计算机 gho文件,u盘里只有gho文件怎么重装win7系统图解u盘里只有gho文件怎么重装win7系统图解,windows7系统现在还是主流系统,有朋友的windows7系统出现问题了,现在u盘里只有gho文件怎么重装win7系统,这是他们遇到u盘怎么重装win7系统的问题了,那么就让小编分享一个u盘里只有gho文件怎么重装win7系统图解给大家吧。u盘里只有gho文件怎么重装win7系统步骤:工具/原料WIN7GHOST系统镜像(可以从网上下载)大于2G…

    2022年7月12日
    26
  • linux默认关闭防火墙(win10永久关闭防火墙命令)

    Linux关闭防火墙命令问题:老是关闭防火墙太麻烦,所以选择彻底关闭防火墙,发现每次都记不住命令!特此记录

    2022年4月15日
    72
  • git 修改ssh端口

    git 修改ssh端口SSH 默认端口为 22 而 Git 的访问是基于 SSH 的 通常我们会更改服务器的 SSH 端口号 即当 SSH 的端口不是 22 上时 Git 访问会出现 ssh connecttohos comport22 Connectionti Theremoteend 无论客户端是在 windows 还是 Linux 配置访问的

    2025年7月31日
    4
  • UML图之四——活动图

    UML图之四——活动图点击打开链接活动图是一种流程图,用来描述活动的序列,从一个活动到另一个活动的控制流。活动图的作用:描述用例,描述类的操作。 活动图的构成必要组成元素:1、活动:命令的执行,活动的进行。图符表示:2、状态:开始状态,结束状态。图符表示: 3、转移:活动之间,活动与状态之间的转换。4、判断:对一个动作或者状态进行判断,然后选择要执行的下一步操作。

    2022年5月5日
    42
  • Django(62)自定义认证类「建议收藏」

    Django(62)自定义认证类「建议收藏」前言如果我们不用使用drf那套认证规则,我们想自定义认证类,那么我们首先要知道,drf本身是如何定义认证规则的,也就是要查看它的源码是如何写的源码分析源码的入口在APIView.py文件下的di

    2022年7月29日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号