表达式求值问题-双栈模板化实现

news/2024/7/8 4:28:17

        好久不见,真的很久都没有更新博客了,最近很多事情,所以比较忙碌,没有时间每天都学算法,但是我会挤时间尽量做到,每两三天就更新博客,我会努力的,加油~

    前言:计算器都见过吧,我们今天要讲的就是类似于计算器计算数据的简单实现,我们需要注意一些问题,比如运算符优先级,运算顺序等等问题,话不多说,冲冲冲!!!

目录

1.问题引入

2.问题分析及解决方法

如何设计优先级问题?

设计计算函数和启动计算条件

完整代码(可做为表达式计算模板使用)

3.金句频道


1.问题引入

2.问题分析及解决方法

       首先,我们先来看一下整体思路:对于一个表达式,我们会读入括号,运算符和数字三种字符,我们需要将这些字符区分开再进行计算,为了保证运算的正确性,由运算符带来的优先级问题是我们解决这个问题的关键,解决了运算符优先级问题,我们就可以将运算符和数字分别存入一个栈中,用读取到' ) '和读取到优先级比已经保存在栈内的运算符来作为启动计算的条件(读到右括号,我们就可以将整个括号内部的部分算出来,再将算得结果压入保存数字的栈中用于后续的计算,而对于读取到优先级低的运算符,因为我们以栈存储数据,导致我们在计算的时候就会按逆序进行计算,所以,我们每次读取到一个运算符优先级低于栈顶的字符,都要先将栈内的运算符优先级高的运算符的结果算出,从而不影响运算顺序),最后,我们的运算符栈内如果还剩下元素,直接计算即可。

如何设计优先级问题?

       这里方法就有很多了,既可以用一个专门的函数来实现,也可以用STL的map键值来实现等等,这里我们采用第二种方法,该方法比较简单且代码易扩展,方便后序添加运算符。

unordered_map<char, int> p{ {'+',1},{'-',1},{'*',2},{'/',2} };//用来表示运算符的优先级,数字越大表示运算优先级越高

设计计算函数和启动计算条件

//计算函数
void f()
{
	//这里需要注意,我们的栈内保存的待运算数字和运算顺序是反着的,会影响减法和除法的计算
	auto b = num.top(); num.pop();
	auto a = num.top(); num.pop();
	auto c = op.top(); op.pop();
	if (c == '+')
		num.push(a + b);
	else if (c == '-')
		num.push(a - b);
	else if (c == '*')
		num.push(a * b);
	else if (c == '/')
		num.push(a / b);
	//如果想要再拓展其他运算,可在此处继续写下去

}

//计算启动条件
else if (s[i] == '(')//如果是左括号,直接入栈等待右括号到来再计算
			op.push(s[i]);
		else if (s[i] == ')')//右括号,准备开始计算结果
		{
			while (op.top() != '(') f();//做括号内的计算
			op.pop();//弹出左括号
		}
		else
		{
			while (!op.empty() && p[op.top()] >= p[s[i]]) f();//如果遇到优先级比前面已经入栈的运算符的优先极低的,则要先解决栈内的计算再将该优先级高的字符入栈
			op.push(s[i]);
		}

完整代码(可做为表达式计算模板使用)

#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
const int maxn = 1e5 + 10;

stack<int >num;
stack<char> op;//运算符

unordered_map<char, int> p{ {'+',1},{'-',1},{'*',2},{'/',2} };//用来表示运算符的优先级,数字越大表示运算优先级越高

void f()
{
	//这里需要注意,我们的栈内保存的待运算数字和运算顺序是反着的,会影响减法和除法的计算
	auto b = num.top(); num.pop();
	auto a = num.top(); num.pop();
	auto c = op.top(); op.pop();
	if (c == '+')
		num.push(a + b);
	else if (c == '-')
		num.push(a - b);
	else if (c == '*')
		num.push(a * b);
	else if (c == '/')
		num.push(a / b);
	//如果想要再拓展其他运算,可在此处继续写下去

}
int main()
{
	string s;
	cin >> s;
	for (int i = 0; i < s.size(); i++)
	{
		if (isdigit(s[i]))//注意,这里需要注意10以上的数,不能只看一个字符就完了
		{
			int j = i;
			int temp = 0;
			while (j < s.size() && isdigit(s[j]))
			{
				temp = temp * 10 + s[j++] - '0';
			}
			i = j-1;//j在退出循环之前已经自增了,所以要减去
			num.push(temp);
		}
		else if (s[i] == '(')//如果是左括号,直接入栈等待右括号到来再计算
			op.push(s[i]);
		else if (s[i] == ')')//右括号,准备开始计算结果
		{
			while (op.top() != '(') f();//做括号内的计算
			op.pop();//弹出左括号
		}
		else
		{
			while (!op.empty() && p[op.top()] >= p[s[i]]) f();//如果遇到优先级比前面已经入栈的运算符的优先极低的,则要先解决栈内的计算再将该优先级高的字符入栈
			op.push(s[i]);
		}
	}
	//如果最后栈内还剩下字符,直接计算即可
	while (op.size()) f();
	printf("%d\n", num.top());

	return 0;
}

     我们这里将计算函数和优先级单独设计,目的就是增加代码的可复用性,main函数内部没有涉及运算符的种类和其他的特殊处理,将特异性的功能封装成函数方便后序增添功能。

3.金句频道

       常常熬不住的时候也想找个靠山靠一下,可怎么找都会发现,有的山长满荆棘,有的山上全是野兽,所以你应该是自己的那座山。过度的依赖总会失掉自我,变得被动,不要总是整天“大佬带我飞”,让自己强起来才是一芳永逸的事。要相信每一次普通的改变,都可能改变原本的普通。

 


http://lihuaxi.xjx100.cn/news/1117194.html

相关文章

SpringBoot基础篇1(搭建环境+基础配置)

一、SpingBoot入门案例 SpringBoot是用来简化Spring应用的初始搭建以及开发过程。 先快速搭建一个SpringBoot&#xff1a; 创建一个空project&#xff0c;再创建SpringBoot模块。 点击Create&#xff0c;出现以下页面配置成功 创建一个控制器测试一下&#xff1a; RestCo…

SeaweedFS学习笔记:调优

文章目录 1. 使用 LevelDB 作为索引的存储2. 预先分配volume file的磁盘空间3. 提高写并发4. 提供读并发5. 增加更多的硬盘驱动器6. 提高用户打开文件的限制数7. 内存消耗7.1 内存中的索引7.2 并发读 8. 当网络不稳定时 1. 使用 LevelDB 作为索引的存储 在启动Volume server时…

AI 不会取代打工人,使用 AI 的人才会

一、被AI端掉饭碗之前&#xff0c;提升自己的硬核实力 AI工具带来了工业革命级别的效率提升&#xff0c;除了强大&#xff0c;更多的引发了打工人的集体焦虑&#xff1a;“我的活ai都能干了&#xff0c;那我做什么呢&#xff1f;” 当然&#xff0c;还有另一种更积极的解答&a…

【PSO-LSTM】基于PSO优化LSTM网络的电力负荷预测(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

目标检测 pytorch复现CenterNet目标检测项目

目标检测 pytorch复现CenterNet目标检测项目 1、项目创新点2、CenterNet网络结构3、CenterNet的模型计算流程如下&#xff1a;4、详细实现原理4.1、heatmap(热力图)理解和生成4.1.1 heatmap生成4.1.2 heatmap高斯函数半径的确定 4.1.3 CenterNet中生成高斯核的部分代码进行解析…

生产问题排查技巧总结

生产问题排查技巧总结 1.背景2.排查问题技巧3.重视问题4.问题分类 1.背景 最近组内入职的新人比较多&#xff0c;大家排查问题比较费时间&#xff0c;也比较痛苦&#xff0c;我抽时间整理了一下我自己常用的排查问题的思路和技巧&#xff0c;在自己的博客里也分享一下。 程序…

AI绘画:Lora模型训练完整流程!

关于AI绘画(基于Stable Diffusion Webui)&#xff0c;我之前已经写过三篇文章&#xff0c;分别是 软件安装&#xff0c;基本的使用方法&#xff0c;微调模型LoRA的使用。 整体来说还是比简单的&#xff0c;搞个别人的模型&#xff0c;搞个提示词就出图了。今天来一个有些难度…