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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1549419.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

USB 3.1 标准 B 型连接器的接口定义与引脚分配

连接器 USB 3.1 规范定义了以下连接器&#xff1a; 超速标准 A 插头和插座&#xff1b;超速标准 B 插头和插座&#xff1b;超速 Micro B 插头和插座&#xff1b;超速 Micro A 插头&#xff1b;超速 Micro-AB 插座。 所有超速连接器具有相同的配合接口并且彼此兼容。 下表列…

腾讯云SDK购买流程

音视频终端 SDK 需购买对应 License/套餐获得使用授权&#xff0c;本文将对购买 License/套餐的操作进行详细指引。 您可首先参考计费概述 确认您需要购买的内容&#xff0c;随后参考本文进行购买。本文仅提供 SDK 授权费用所需资源的购买&#xff0c;如果您需要使用其他相关云…

锦天云中秋之夜团圆家宴圆满成功

2024年9月7日&#xff0c;锦天云&#xff08;深圳&#xff09;计算机设备有限公司 在中国深圳成功举办了“融创智合•月满锦天 锦天云中秋之夜团圆家宴。本次盛会吸引了来自各行业的精英和合作伙伴&#xff0c;大家齐聚一堂&#xff0c;共同庆祝这一传统佳节&#xff0c;此次活…

SPI驱动学习七(SPI_Slave_Mode驱动程序框架)

目录 一、SPI_Slave_Mode驱动程序框架1. Master和Slave模式差别1.1 主设备 (Master)1.2 从设备 (Slave)1.3 示例 2. SPI传输概述2.1 数据组织方式2.2 SPI控制器数据结构 3. SPI Slave Mode数据传输过程4. 如何编写程序4.1 设备树4.2 内核相关4.3 简单的示例代码4.3.1 master和s…

K8S真正删除pod

假设k8s的某个命名空间如&#xff08;default&#xff09;有一个运行nginx 的pod&#xff0c;而这个pod是以kubectl run pod命令运行的 1.错误示范&#xff1a; kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了&#xff0c;但k8s很快自动创建新的pod,但是…

今日指数项目股票成交量对比功能

股票成交量对比功能 1. 股票成交量对比功能分析 1.1 模型示列 功能描述&#xff1a;统计A股大盘T日和T-1日成交量对比功能&#xff08;成交量为沪深两市成交量之和&#xff09; 1.2 接口示列 返回数据格式 服务路径&#xff1a;/api/quot/stock/tradeAmt 服务方法&#xf…

PCL uniform_sampling均匀采样抽稀

目录 一、概述二、代码三、结果 一、概述 均匀采样抽稀点云。 二、代码 uniform_sampling.cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/keypoints/uniform_s…

[Admin] Things Need to Know

List View Bulk Actions Highlight: To take bulk actions on all of the available records in a list, you click the bulk action button without selecting any records.

利士策分享,攀登职场高峰:成功者的十大特质

利士策分享&#xff0c;攀登职场高峰&#xff1a;成功者的十大特质 在职场这个竞争激烈的舞台上&#xff0c;那些能够迅速崛起、实现职业辉煌的佼佼者&#xff0c;往往凭借一系列独特且鲜明的特质脱颖而出。以下是对这些特质的深入探讨&#xff1a; 第一章&#xff1a;高情商的…

怎么不用付费直接编辑pdf?5款pdf在线编辑器免费推荐给你!

在我们日常工作中&#xff0c;可能会经常需要直接编辑修改pdf内容&#xff0c;例如&#xff0c;在将文档发送给其它人之前&#xff0c;您可能需要进行一些修改&#xff1b;或者当扫描的文本出现错误时&#xff0c;您也需要进行修正。此时&#xff0c;如果有一款在线编辑器&…

黑神话悟空小西天

游戏里我们一开始就出现一个很可爱的小和尚&#xff0c;当脚步声传来&#xff0c;小和尚化身为一尊弥勒佛&#xff0c;而这尊弥勒佛的大小和位置都在说&#xff0c;这里没有弥勒佛的位置。 随后天命人进入一片雪地&#xff0c;遇到了赤尻马猴&#xff0c;打跑赤尻马猴&#xff…

从哪里下载高清解压视频素材?推荐五个优质素材资源网站

想制作吸引人的抖音小说推文&#xff0c;但不知道从哪里获取高清解压视频素材&#xff1f;今天就为大家推荐五个优秀的网站&#xff0c;帮助你轻松找到所需的素材&#xff0c;提升你的创作质量。 首先是蛙学网 作为国内顶级的短视频素材网站&#xff0c;蛙学网提供了丰富的4K高…

Transformer是不是BERT、GPT的妈?看完就知道了

Transformer变异衍生出来了两个超强悍的预训练模型 一、Transformer模型 Transformer是近年来深度学习领域中备受瞩目的模型之一&#xff0c;其核心思想是通过自注意力机制和位置编码来捕捉输入序列中的长距离依赖关系。 自注意力机制让模型在处理每个输入元素时能够关注到所有…

Proe 5.0资源百度网盘下载 附详细安装步骤

如大家所了解的&#xff0c;Proe又称作Pro/E&#xff0c;是比较常用的CAD/CAM/CAE软件之一&#xff0c;也是一款功能齐全的模具和产品设计三维的工具。 Proe在传统机械设计、家电设计以及模具设计方面&#xff0c;优势很突出。 首先&#xff0c;建模采用参数化设计&#xff0…

Qt/C++ 解决调用国密SM3,SM4加密解密字符串HEX,BASE64格式转换和PKCS5Padding字符串填充相关问题

项目中遇到了需要与JAVA WEB接口使用SM3,SM4加密数据对接的需求&#xff0c;于是简单了解了下SM3与SM4加密算法在C环境下的实现。并使用Qt/C还原了在线SM3国密加密工具和在线SM4国密加密解密工具网页的示例功能的实现 目录导读 前言SM3算法简介SM4算法简介 实现示例字符串HEX,B…

气膜影院:沉浸式观影体验的全新选择—轻空间

随着观影需求的不断提升&#xff0c;传统影院形式已经无法满足观众对更高沉浸感和视觉体验的追求。气膜影院作为一种新兴的观影场所&#xff0c;以其独特的球幕结构和先进的技术手段&#xff0c;为观众带来了全新的沉浸式视听体验。 全景沉浸式观影体验 气膜影院采用球幕设计&a…

Awcing 799. 最长连续不重复子序列

Awcing 799. 最长连续不重复子序列 解题思路: 让我们找到一个数组中&#xff0c;最长的 不包含重复的数 的连续区间的长度。 最优解是双指针算法&#xff1a; 我们用 c n t [ i ] cnt[i] cnt[i]记录 i i i 这个整数在区间内出现的次数。(因为每个数的大小为 1 0 5 10^5 105, …

赵长鹏今日获释,下一步会做什么?币安透露2024年加密货币牛市的投资策略!

中国时间2024年9月28日&#xff0c;加密货币行业的风云人物赵长鹏&#xff08;Changpeng Zhao&#xff0c;简称CZ&#xff09;终于从监狱获释。他因在担任币安首席执行官期间未能有效执行反洗钱(AML)计划而被判刑四个月。赵长鹏的获释引发了广泛关注&#xff0c;不仅因为他是全…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…

python全栈开发《41.列表的clear函数》

1.clear的功能 一次性将当前列表中所有的数据清空。 2.clear的用法 target [1,2,3,4,5,6] target.clear() print(target) 运行结果&#xff1a; /Users/llq/PycharmProjects/pythonlearn/pythonlearn/python_list/bin/python /Users/llq/PycharmProjects/pythonlearn/python_l…