AcWing 3302. 表达式求值(栈)

该博客主要讨论如何使用栈解决表达式求值的问题,重点在于建立双栈结构,一个用于存储操作数,一个用于存储运算符。通过比较运算符的优先级并处理括号,逐步计算出表达式的值。示例代码使用C++实现,讲解了如何处理加、减、乘、除四种运算,并特别提到了整除的处理方式。整个过程中,注意了数字的处理、括号的匹配以及运算符的优先级规则。
摘要由CSDN通过智能技术生成

题目链接 :点击查看

题目描述 :

给定一个表达式,其中运算符仅包含 +,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。

注意:

  • 数据保证给定的表达式合法。
  • 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现。
  • 题目保证表达式中所有数字均为正整数。
  • 题目保证表达式在中间计算过程以及结果中,均不超过 2^31−1。
  • 题目中的整除是指向 0 取整,也就是说对于大于 00 的结果向下取整,例如 5/3=1,对于小于 00 的结果向上取整,例如 5/(1−4)=−1。
  • C++和Java中的整除默认是向零取整;Python中的整除/默认向下取整,因此Python的eval()函数中的整除也是向下取整,在本题中不能直接使用。

输入输出 

输入

(2+2)*(1+1)

输出

8

题目分析 :

表达式求值问题一般要考虑三个关键点。(1) 建立双栈, 一个操作数栈,一个运算符栈,实现对表达式的运算(2) 比较即将入栈的运算符和运算符栈栈顶的运算符的优先级。如要入栈的运算符优先级较低,则将操作数和运算符出栈计算。反之,直接将运算符入栈。(3)括号情况。要当前字符是左括号,则直接入运算符栈,要是右括号,则要出栈计算,直到遇到左括号(可以看做是(2)的特殊情况,左括号的优先级为0,右括号单独考虑)。为了方便计算,我们定义一个eval()函数每次调用对栈顶部的两个数与运算符进行操作运算,这里要注意,num栈的栈顶元素是第二操作数(作除数,减数,其他两种运算符则无所谓),弹出之后接下来的数才是第一操作数。详见如下代码。

#include<iostream>
#include<cstdio>
#include<string>
#include<stack>
#include<unordered_map>
#include<cstring>
#include<cstdlib>
#include<cctype> 
using namespace std;
stack <int> num;//操作数栈 
stack <int> op;//运算符栈 

unordered_map<char, int> h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};//用hash表记录运算符的优先级 

void eval() {
	
	int a = num.top(); num.pop();//第二个操作数
	int b = num.top(); num.pop();//第一个操作数
	
	char p = op.top(); op.pop();//运算符
	
	int res = 0;//结果 
	if (p == '+') res = b + a;
	if (p == '-') res = b - a;
	if (p == '*') res = b * a;
	if (p == '/') res = b / a;
	
	num.push(res);
} 

int main() {
	string s;
	cin >> s;
	for (int i = 0; i < s.size(); i ++ ) {
		if (isdigit(s[i])) {//数字入栈 
			int x = 0, j = i;//x用来记录数字(一位或是多位) j用来记录位置 
			while (j < s.size() && isdigit(s[j])) {
				x = x * 10 + (s[j] - '0'); 
				j ++ ;
			} 
			num.push(x);//数字入栈 
			i = j - 1; 
		} 
		//左括号无优先级直接入栈 
		else if (s[i] == '(')  op.push(s[i]);
		//遇到右括号计算括号里面的, 遇到左括号结束 
		else if (s[i] == ')')  {
		   while (op.top() != '(') {
		   	   eval();
		   }
		   op.pop();//左括号出栈 
		} 
		else {
		   while (op.size() && h[op.top()] >= h[s[i]])  eval();//要入栈的运算符优先级低,则将之前的结果计算出来 
		   op.push(s[i]);// 操作符入栈 
		}
	}
	while (op.size()) eval();
	cout << num.top() << endl;//输出结果  
    return 0;
}

---------------------------------------------------------------------

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在森林中麋了鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值