当前位置: 首页 > news >正文

HJ50-四则运算:栈的运用、中缀表达式转后缀表达式并计算结果

文章目录

  • 题目
  • 一、分析
      • 1.1表达式预处理
      • 1.2中缀表达式转后缀
      • 1.3 后缀表达式计算结果
  • 二、答案


题目

在这里插入图片描述


一、分析

通过利用栈将中缀表达式转换为后缀表达式,在根据后缀表达式计算运算结果。由于包含负数操作数的情况,并且操作数位数不固定为1,因此,需要对输入的表达式进行预处理,将操作数和操作符进行分离,并且将大括号和中括号统一为小括号。

1.1表达式预处理

/// <summary>
/// 预处理表达式
/// </summary>
/// <param name="data">中缀表达式</param>
/// <returns>表达式</returns>
std::vector<std::string>  pretreat(const std::string& data)
{std::string value = data;//->处理括号for (int i = 0; i < value.size(); i++){if (value[i] == '[' || value[i] == '{') value[i] = '(';if (value[i] == ']' || value[i] == '}') value[i] = ')';}//->处理负数,并将运算符与运算数拆分开value = '(' + value + ')';	int index = -1;std::vector<std::string> content;for (int i = 0; i < value.size(); i++){//->负数操作数的情况if (value[i] == '-' && (i - 1) >= 0 && value[i - 1] == '(' && (i + 1) < value.size() && value[i + 1] >= '0' && value[i + 1] <= '9'){index = i;continue;}//->非负数操作数else if (value[i] >= '0' && value[i] <= '9' && index == -1){index = i;}if ((value[i] < '0' || value[i] > '9') && index != -1){content.push_back(value.substr(index, i - index));index = -1;}if ((value[i] < '0' || value[i] > '9') && index == -1){content.push_back(value.substr(i, 1));}}return content;
}

1.2中缀表达式转后缀

1.2.1 对于中缀表达式A+B*(C-D)-E/F转后后缀表达式时,栈中数据变化情况如下。

1.2.2 栈内和栈外操作符的优先级如下。

std::map<std::string, int> isp = { {"#",0}, {"(",1},  {"*",5},  {"/",5},  {"+",3},  {"-",3},  {")",6} };//->栈内操作符的优先级
std::map<std::string, int> icp = { {"#",0}, {"(",6},  {"*",4},  {"/",4},  {"+",2},  {"-",2},  {")",1} };//->栈外操作符的优先级

1.2.3 代码逻辑伪代码如下,可根据此变化设计代码逻辑。

扫描项项类型动作栈变化输出
0“#”进栈#
1A操作数#A
2+操作符isp[“#”] < icp[“+”],进栈#+A
3B操作数#+AB
4*操作符isp[“+”] < icp[“*”],进栈#+*AB
5(操作符isp[“*”] < icp[“(”],进栈#+*(AB
6C操作数#+*(ABC
7-操作符isp[“(”] < icp[“-”],进栈#+*(-ABC
8D操作数#+*(-ABCD
9)操作符isp[“-”] >icp[“)”],退栈#+*(ABCD-
”(“ == “)”,退栈#+*ABCD-
10-操作符isp[“*”] > icp[“-”],退栈#+ABCD-*
isp[“+”] > icp[“-”],退栈#ABCD-*+
isp[“#”] < icp[“-”],进栈#-ABCD-*+
11E操作数#-ABCD-*+E
12/操作符isp[“-”] < icp[“/”],进栈#-/ABCD-*+E
13F操作数#-/ABCD-*+EF
14#操作符isp[“/”] > icp[“#”],退栈#-ABCD-*+EF/
操作符isp[“-”] > icp[“#”],退栈#ABCD-*+EF/-
结束
/// <summary>
/// 判断是否是操作数
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
bool isDigit(std::string& value)
{if (value.empty())return false;return value.back() >= '0' && value.back() <= '9';
}/// <summary>
/// 将中缀表达式转换为后缀表达式
/// </summary>
/// <param name="data">中缀表达式</param>
/// <returns>后缀表达式</returns>
std::vector<std::string> postfix(std::vector<std::string>& content)
{//->定义栈内操作符和栈外操作符的优先级std::map<std::string, int> isp = { {"#",0}, {"(",1},  {"*",5},  {"/",5},  {"+",3},  {"-",3},  {")",6} };//->栈内操作符的优先级std::map<std::string, int> icp = { {"#",0}, {"(",6},  {"*",4},  {"/",4},  {"+",2},  {"-",2},  {")",1} };//->栈外操作符的优先级content.push_back("#");int index = 0;std::vector<std::string> expression;std::string item1 = "#", item2, item3;std::stack<std::string> stack;stack.push(item1);item1 = content[index];index++;while (!stack.empty() && item1 != "#"){if (isDigit(item1)){expression.push_back(item1);item1 = content[index];index++;}else{item2 = stack.top();if (isp[item2] < icp[item1]){stack.push(item1);item1 = content[index];index++;}else if (isp[item2] > icp[item1]){expression.push_back(stack.top());item3 = stack.top();stack.pop();}else{std::string item = stack.top();stack.pop();if (item == "("){item1 = content[index];index++;}}}}return expression;
}

1.3 后缀表达式计算结果

1.3.1 计算后缀表达式ABCD-*+EF/-栈中元素变化情况,逻辑如下。

扫描项项类型动作栈中内容
1栈置空
2A操作数进栈A
3B操作数进栈AB
4C操作数进栈ABC
5D操作数进栈ABCD
6-操作符D、C退栈,计算C-D,结果R1进栈ABR1
7*操作符R1、B退栈,计算B*R1,结果R2进栈BR2
8+操作符R2、B退栈,计算A+R2,结果R3进栈R3
9E操作数进栈R3E
10F操作数进栈R3EF
11/操作符F、E退栈,计算E/F,结果R4进栈R3R4
12-操作符R4、R3退栈。计算R3-R4,结果R5进栈R5
/// <summary>
/// 根据后缀表达式计算结果
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
float calculator(std::vector<std::string>& expression)
{std::stack<float> values;for (int i = 0; i < expression.size(); i++){std::string value = expression[i];if (isDigit(value)){values.push(std::atoi(value.c_str()));}else{float value1 = values.top(); values.pop();float value2 = values.top(); values.pop();switch (value[0]){case '+': values.push(value2 + value1); break;case '-':  values.push(value2 - value1); break;case '*': values.push(value2 * value1); break;case '/': values.push(value2 / value1); break;default:break;}}}return values.top();
}

二、答案

#include  <iostream>
#include <stack>
#include <string>
#include <vector>
#include <map>/// <summary>
/// 判断是否是操作数
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
bool isDigit(std::string& value)
{if (value.empty())return false;return value.back() >= '0' && value.back() <= '9';
}/// <summary>
/// 将中缀表达式转换为后缀表达式
/// </summary>
/// <param name="data">中缀表达式</param>
/// <returns>后缀表达式</returns>
std::vector<std::string> postfix(std::vector<std::string>& content)
{//->定义栈内操作符和栈外操作符的优先级std::map<std::string, int> isp = { {"#",0}, {"(",1},  {"*",5},  {"/",5},  {"+",3},  {"-",3},  {")",6} };//->栈内操作符的优先级std::map<std::string, int> icp = { {"#",0}, {"(",6},  {"*",4},  {"/",4},  {"+",2},  {"-",2},  {")",1} };//->栈外操作符的优先级content.push_back("#");int index = 0;std::vector<std::string> expression;std::string item1 = "#", item2, item3;std::stack<std::string> stack;stack.push(item1);item1 = content[index];index++;while (!stack.empty() && item1 != "#"){if (isDigit(item1)){expression.push_back(item1);item1 = content[index];index++;}else{item2 = stack.top();if (isp[item2] < icp[item1]){stack.push(item1);item1 = content[index];index++;}else if (isp[item2] > icp[item1]){expression.push_back(stack.top());item3 = stack.top();stack.pop();}else{std::string item = stack.top();stack.pop();if (item == "("){item1 = content[index];index++;}}}}return expression;
}/// <summary>
/// 预处理表达式
/// </summary>
/// <param name="data">中缀表达式</param>
/// <returns>表达式</returns>
std::vector<std::string>  pretreat(const std::string& data)
{std::string value = data;//->处理括号for (int i = 0; i < value.size(); i++){if (value[i] == '[' || value[i] == '{') value[i] = '(';if (value[i] == ']' || value[i] == '}') value[i] = ')';}//->处理负数,并将运算符与运算数拆分开value = '(' + value + ')';	int index = -1;std::vector<std::string> content;for (int i = 0; i < value.size(); i++){//->负数操作数的情况if (value[i] == '-' && (i - 1) >= 0 && value[i - 1] == '(' && (i + 1) < value.size() && value[i + 1] >= '0' && value[i + 1] <= '9'){index = i;continue;}//->非负数操作数else if (value[i] >= '0' && value[i] <= '9' && index == -1){index = i;}if ((value[i] < '0' || value[i] > '9') && index != -1){content.push_back(value.substr(index, i - index));index = -1;}if ((value[i] < '0' || value[i] > '9') && index == -1){content.push_back(value.substr(i, 1));}}return content;
}/// <summary>
/// 根据后缀表达式计算结果
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
float calculator(std::vector<std::string>& expression)
{std::stack<float> values;for (int i = 0; i < expression.size(); i++){std::string value = expression[i];if (isDigit(value)){values.push(std::atoi(value.c_str()));}else{float value1 = values.top(); values.pop();float value2 = values.top(); values.pop();switch (value[0]){case '+': values.push(value2 + value1); break;case '-':  values.push(value2 - value1); break;case '*': values.push(value2 * value1); break;case '/': values.push(value2 / value1); break;default:break;}}}return values.top();
}int main()
{std::string data;std::cin >> data;std::vector<std::string> content = pretreat(data);std::vector<std::string> expression = postfix(content);std::cout << calculator(expression);return 0;
}

相关文章:

HJ50-四则运算:栈的运用、中缀表达式转后缀表达式并计算结果

文章目录 题目一、分析1.1表达式预处理1.2中缀表达式转后缀1.3 后缀表达式计算结果 二、答案 题目 一、分析 通过利用栈将中缀表达式转换为后缀表达式&#xff0c;在根据后缀表达式计算运算结果。由于包含负数操作数的情况&#xff0c;并且操作数位数不固定为1&#xff0c;因此…...

C++编程:实现简单的高精度时间日志记录小程序

0. 概述 为了检查是否存在系统时间跳变&#xff0c;本文使用C实现了一个简单的高精度时间日志记录小程序。该程序能够每隔指定时间&#xff08;默认40毫秒&#xff09;记录一次系统时间到文件中&#xff0c;并具备以下功能&#xff1a; 自定义时间间隔和文件名&#xff1a;通…...

QQ机器人搭建

使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人 文章目录 使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人前言编写机器人代码机器人监听群聊进行文字回复机器人监听群聊进行图片回复机器人监听群聊进行文件发送机器人监听群聊进行视频发送机器人监听群聊进行语…...

flink设置保存点和恢复保存点

增加了hdfs package com.qyt;import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple.Tuple2;import org.apache.flink.runtime.state.storage.FileSystemCheckpointStorage;import org.apache.flink.streaming.api.datastream.Dat…...

使用python获取百度一下,热搜TOP数据详情

一、查找对应链接 # 警告&#xff1a;以下代码仅供学习和交流使用&#xff0c;严禁用于任何违法活动。 # 本代码旨在帮助理解和学习编程概念&#xff0c;不得用于侵犯他人权益或违反法律法规的行为。 1、打开百度页面 百度一下&#xff0c;你就知道 2、点击F12 或 右键鼠标…...

Go conc库学习与使用

文章目录 主要功能和特点conc 的安装典型使用场景示例代码并行执行多个 Goroutines错误处理限制并发 Goroutines 数量使用 context.Context 进行任务控制 常见问题1. **任务中发生 panic**原因&#xff1a;解决方法&#xff1a; 2. **conc.Group 重复调用 Wait()**原因&#xf…...

大模型prompt先关

对于未出现的任务&#xff0c;prompt编写技巧&#xff1a; 1、假设你是资深的摘要生成专家&#xff0c;根据提供的内容&#xff0c;总结对应的摘要信息。请生成一个指令&#xff0c;指令中带有一个使用例子。直接提供给大型模型以执行此任务。 2、基于大模型提供的内容再进行二…...

尚品汇-自动化部署-Jenkins的安装与环境配置(五十六)

目录&#xff1a; 自动化持续集成 &#xff08;1&#xff09;环境准备 &#xff08;2&#xff09;初始化 Jenkins 插件和管理员用户 &#xff08;3&#xff09;工作流程 &#xff08;4&#xff09;配置 Jenkins 构建工具 自动化持续集成 互联网软件的开发和发布&#xf…...

【尚跑】2024铜川红色照金半程马拉松赛,大爬坡152安全完赛

1、赛事背景 2024年9月22日8点&#xff0c;2024铜川红色照金半程马拉松赛于照金1933广场鸣枪起跑&#xff01; 起跑仪式上&#xff0c;6000位选手们合唱《歌唱祖国》&#xff0c;熟悉的旋律响彻陕甘边革命根据地照金纪念馆前&#xff0c;激昂的歌声凝聚心中不变的热爱。随着国…...

WPS中让两列数据合并的方法

有这样一个需求&#xff0c;就是把A列数据和B列数据进行合并&#xff08;空单元格略过&#xff09;具体实现效果如图下&#xff1a; 该如何操作呢&#xff1f; 首先在新的一列第一个单元格中输入公式"A1&B1" 然后回车&#xff0c;就出现了两列单元格数据合并的效…...

使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)

centos系统配置阿里云yum源 因为centos7官方停止维护&#xff0c;自带yum源用不了了&#xff0c;所以可以更换成阿里云yum源 方法&#xff1a; 使用root权限执行以下语句 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo CentOS…...

《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析

目录 一、透视变换 1、什么是透视变换 2、操作步骤 1&#xff09;选择透视变换的源图像和目标图像 2&#xff09;确定透视变换所需的关键点 3&#xff09;计算透视变换的变换矩阵 4&#xff09;对源图像进行透视变换 5&#xff09;对变换后的图像进行插值处理 二、轮廓检测…...

Linux 线程互斥

前言 对于初学线程的伙伴来讲&#xff0c;多线程并发访问导致的数据不一致问题&#xff0c;总是让人陷入怀疑&#xff0c;很多人只是给你说加锁&#xff01;但没有人告诉你为什么&#xff1f;本篇博客将详解&#xff01; 目录 前言 一、线程互斥 • 为什么票会出现负数的情…...

【Redis 源码】6AOF持久化

1 AOF功能说明 aof.c 文件是 Redis 中负责 AOF&#xff08;Append-Only File&#xff09;持久化的核心文件。AOF 持久化通过记录服务器接收到的每个写命令来实现数据的持久化。这样&#xff0c;在 Redis 重启时&#xff0c;可以通过重放这些命令来恢复数据。 2 AOF相关配置 a…...

6.MySQL基本查询

目录 表的增删查改Insert&#xff08;插入&#xff09;插入替换插入替换2 Retrieve&#xff08;查找&#xff09;SELECT 列全列查找指定列查询查询字段为表达式为查询结果指定别名结果去重 WHERE 条件order by子句筛选分页结果 Update&#xff08;更新&#xff09;delete&#…...

Linux字符设备驱动开发

Linux 字符设备驱动开发是内核模块开发中的一个重要部分&#xff0c;主要用于处理字节流数据设备&#xff08;如串口、键盘、鼠标等&#xff09;。字符设备驱动的核心任务是定义如何与用户空间程序交互&#xff0c;通常通过一组文件操作函数进行。这些函数会映射到 open、read、…...

HTML5+JavaScript绘制闪烁的网格错觉

HTML5JavaScript绘制闪烁的网格错觉 闪烁的网格错觉&#xff08;scintillating grid illusion&#xff09;是一种视觉错觉&#xff0c;通过简单的黑白方格网格和少量的精心设计&#xff0c;能够使人眼前出现动态变化的效果。 闪烁的栅格错觉&#xff0c;是一种经典的视觉错觉…...

每日OJ题_牛客_拼三角_枚举/DFS_C++_Java

目录 牛客_拼三角_枚举/DFS 题目解析 C代码1 C代码2 Java代码 牛客_拼三角_枚举/DFS 拼三角_枚举/DFS 题目解析 简单枚举&#xff0c;不过有很多种枚举方法&#xff0c;这里直接用简单粗暴的枚举方式。 C代码1 #include <iostream> #include <algorithm> …...

[uni-app]小兔鲜-01项目起步

项目介绍 效果演示 技术架构 创建项目 HBuilderX创建 下载HBuilderX编辑器 HBuilderX/创建项目: 选择模板/选择Vue版本/创建 安装插件: 工具/插件安装/uni-app(Vue3)编译器 vue代码不能直接运行在小程序环境, 编译插件帮助我们进行代码转换 绑定微信开发者工具: 指定微信开…...

安全的价值:构建现代企业的基础

物理安全对于组织来说并不是事后才考虑的问题&#xff1a;它是关键的基础设施。零售商、医疗保健提供商、市政当局、学校和所有其他类型的组织都依赖安全系统来保障其人员和场所的安全。 随着安全技术能力的不断发展&#xff0c;许多组织正在以更广泛的视角看待他们的投资&am…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...