中后缀表达式

一、利用后缀表达式进行计算

1)解题思路

  1. 如果当前字符串是操作数,就将该操作数入栈;
  2. 如果当前字符串是操作符,就取栈顶的两个操作数进行运算(注意:第一个出栈的数为计算时的右操作数;第二个出栈的数为计算是的左操作数),并将运算结果重新入栈;
  3. 重复上面两个步骤,直到字符串遍历完:最后栈里面的值就是计算结果。

2)代码

int evalRPN(vector<string>& tokens) {stack<int> st;// 遍历字符for(auto& e : tokens){// 如果遇到的是运算符,取出栈中的两个元素运算,并将运算结果入栈if(e == "+" || e == "-" || e == "*" || e == "/"){int num2 = st.top();st.pop();int num1 = st.top();st.pop(); if(e == "+")st.push(num1+num2);if(e == "-")st.push(num1-num2);if(e == "*")st.push(num1*num2);if(e == "/")st.push(num1/num2);}// 如果是操作数,如入栈else{st.push(stoi(e));}} return st.top();}
};

3)注意点

如果当前字符串为操作数时,需要先使用 stoi() 函数将字符串转化为数字后,将其入栈。

题目链接:

150. 逆波兰表达式求值 - 力扣(LeetCode)

二、中缀表达式转后缀表达式

1)解题思路

  1. 如果当前字符为操作数,直接输出;
  2. 如果当前字符为操作符,判断当前栈是否为空:
    1. 如果栈为空,将该操作符入栈;
    2. 如果栈不为空,将该操作符与栈顶元素比较优先级:
      1. 如果当前操作符优先级高,入栈;
      2. 如果当前操作符优先级相等或较低,输出栈顶元素。

还需要考虑,括号带来的优先级问题:不能仅仅根据运算符本身的优先级进行比较。

这里有好几种处理方法,在这里我介绍一种:

  1. 遇到 ( 时,将它入栈,并且认为它的优先级是最低的,这样才能保证括号内部的操作符才能入栈;
  2. 同时遇到 ) 时,我们还是认为它的优先级是最低的,这样才能保证括号内部的操作符能够出栈进行计算,并且出栈 - 后,并且遇到( 后,将其出栈。
  3. 最后如果栈空也不进行入栈操作,并进行下一个操作的判断。

括号的特殊处理,总结一下:

  1. ()的优先级最低;
  2. ( 不进行优先级的比较,直接入栈;
  3. ) 进行比较,输出栈顶元素,直到遇到( 。

下面举个例子,模拟一个这个过程:

当将中缀表达式1+2*(4-5*2)+6/7转化为后缀表达式时,可以按照以下步骤进行:

  1. 创建一个空栈和一个空列表(用于存放后缀表达式)。

  2. 从左到右遍历中缀表达式中的每个元素,按照以下规则处理:

    • 遇到数字时,直接加入到后缀表达式列表中。

    • 遇到运算符时,分两种情况:

      • 如果栈为空或者栈顶元素为左括号,将当前运算符压入栈中。
      • 否则,如果当前运算符的优先级小于等于栈顶运算符的优先级,则将栈顶运算符弹出并加入到后缀表达式列表中,直到栈顶运算符的优先级小于当前运算符的优先级或者栈为空,然后将当前运算符压入栈中。
    • 遇到左括号时,将其压入栈中。

    • 遇到右括号时,依次弹出栈顶元素并加入到后缀表达式列表中,直到遇到左括号为止。注意:左右括号不应该加入到后缀表达式列表中。

  3. 如果中缀表达式已经遍历完毕,则将栈中剩余的运算符依次弹出并加入到后缀表达式列表中。

  4. 后缀表达式列表即为转换得到的后缀表达式。

以下是将中缀表达式1+2*(4-5*2)+6/7转化为后缀表达式的详细过程:

  1. 初始化栈和后缀表达式列表为空。

  2. 从左到右遍历中缀表达式:

    • 遇到字符'1',加入后缀表达式列表:['1']
    • 遇到字符'+',将其压入栈中:栈:['+']
    • 遇到字符'2',加入后缀表达式列表:['1', '2']
    • 遇到字符'*',将其压入栈中:栈:['+', '*']
    • 遇到字符'(',将其压入栈中:栈:['+', '*', '(']
    • 遇到字符'4',加入后缀表达式列表:['1', '2', '4']
    • 遇到字符'-',将其压入栈中:栈:['+', '*', '(', '-']
    • 遇到字符'5',加入后缀表达式列表:['1', '2', '4', '5']
    • 遇到字符'*',将其压入栈中:栈:['+', '*', '(', '-', '*']
    • 遇到字符'2',加入后缀表达式列表:['1', '2', '4', '5', '2']
    • 遇到字符')',弹出栈顶元素并加入后缀表达式列表,直到遇到左括号为止:['1', '2', '4', '5', '2', '*', '-']
    • 弹出左括号'('。
    • 遇到字符'+',将其压入栈中:栈:['+', '+']
    • 遇到字符'6',加入后缀表达式列表:['1', '2', '4', '5', '2', '*', '-', '6']
    • 遇到字符'/',将其压入栈中:栈:['+', '+', '/']
    • 遇到字符'7',加入后缀表达式列表:['1', '2', '4', '5', '2', '*', '-', '6', '7']
  3. 中缀表达式已经遍历完毕,将栈中剩余的运算符依次弹出并加入到后缀表达式列表中:['1', '2', '4', '5', '2', '*', '-', '6', '7', '/', '+', '+']

  4. 后缀表达式为1 2 4 5 2 * - * + 6 7 / +

这就是将中缀表达式1+2*(4-5*2)+6/7转化为后缀表达式的详细过程。

2)代码

#include <iostream>
#include <stack>
#include <string>
#include <vector>bool isOperator(char ch) {return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}int getPriority(char op) {if (op == '+' || op == '-')return 1;else if (op == '*' || op == '/')return 2;return 0;
}std::vector<std::string> infixToPostfix(const std::string& infix) {std::vector<std::string> postfix;std::stack<char> opStack;for (unsigned i = 0; i < infix.length(); ++i) {char ch = infix[i];if (ch == ' ') {continue;}else if (isdigit(ch)) {std::string num;while (i < infix.length() && (isdigit(infix[i]) || infix[i] == '.')) {num += infix[i++];}--i;postfix.push_back(num);}else if (isOperator(ch)) {while (!opStack.empty() && opStack.top() != '(' &&getPriority(opStack.top()) >= getPriority(ch)) {postfix.push_back(std::string(1, opStack.top()));opStack.pop();}opStack.push(ch);}else if (ch == '(') {opStack.push(ch);}else if (ch == ')') {while (!opStack.empty() && opStack.top() != '(') {postfix.push_back(std::string(1, opStack.top()));opStack.pop();}opStack.pop(); // Discard '('}}while (!opStack.empty()) {postfix.push_back(std::string(1, opStack.top()));opStack.pop();}return postfix;
}int main() {std::string infixExpression = "1+2*(4-5*2)+6/7";std::vector<std::string> postfixExpression;postfixExpression = infixToPostfix(infixExpression);for (const auto& token : postfixExpression) {std::cout << token << " ";}std::cout << std::endl;return 0;
}

遇到 ( 时,将它入栈,并且认为它的优先级是最低的,这样才能保证括号内部的操作符才能入栈;

同时遇到 ) 时,我们还是认为它的优先级是最低的,这样才能保证括号内部的操作符能够出栈进行计算,并且出栈 - 后,并且遇到( 后,将其出栈,最后如果栈空也不进行入栈操作,并进行下一个操作的判断。

同时也可以使用增加一个flag标签的方法:

我们可以将这个flag初始化为0,只有遇到( 时,将flag = 1,通过flag的值判断下一个操作符的优先级,当flag = 1时,无论下一个操作符是什么,我们都认为它的优先级是高于此时栈顶操作符的,并进行入栈操作。当遇到)时,将flag置为0;

也可以使用递归,将()内部的表达式用一个新的栈进行计算,并将结果返回。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【力扣题解】P144-二叉树的前序遍历-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P144-二叉树的前序遍历-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f30…

blender使用faceit绑定自己的表情动作

blender使用faceit绑定自己的表情控制模型 faceit是个神器&#xff0c;来记录一下如何让表情动起来保持相对位置头部分离&#xff0c;方便后续绑定faceitfaceit的注册rig生成地标Animate可以修正表情烘培之前记得保存使用Faceit的整个流程 faceit是个神器&#xff0c;来记录一下…

2024 年网络安全展望:未来是什么?

为了建立强大的网络安全计划&#xff0c;组织必须首先了解整体威胁环境不断变化的性质。 人工智能在成为安全团队的帮助之前&#xff0c;将为网络犯罪分子带来巨大的福音。 网络犯罪分子和不良行为者将受益于先进人工智能工具的广泛部署&#xff0c;然后他们的目标才能建立人…

python爬虫进阶-每日一学(GIF验证码识别)

目的 学习更多的python反爬虫策略 测试网址 http://credit.customs.gov.cn/ccppserver/verifyCode/creator分析 01 下载gif图片 02 使用ddddocr逐帧识别 03 如指定字符串出现次数大于等于3&#xff0c;则认定为正确的识别结果 经验证&#xff0c;识别成功率95%源码 #!/usr…

【网络奇缘】——奈氏准则和香农定理从理论到实践一站式服务|计算机网络

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 失真 - 信号的变化 影响信号失真的因素&#xff1a; ​编辑 失真的一种现象&#xff1a;码间…

162TB全球卫星地图瓦片服务

这里再为你分享长光的另一款重量级产品&#xff0c;即《吉林一号国产化全球遥感底图瓦片服务》&#xff0c;你可以把它简单地理解为是一套全球离线地图服务系统。 为了行文方便&#xff0c;我们在本文暂且称之为“长光全球瓦片系统”。 《长光全球瓦片系统》参数 《长光全球…

UE5 C++(九)— 静态、动态加载类和资源

文章目录 前提静态加载类和资源静态加载资源静态加载类 动态加载类和资源动态资源动态加载类 前提 有必要说一下&#xff0c;静态这块内容加载时我用UE5.2版本出现调用静态资源不是显示问题&#xff0c;修改后容易崩。所以&#xff0c;这里不建议5.2版本&#xff0c;直接用5.3…

Python pandas 操作 excel 详解

文章目录 1 概述1.1 Series 和 DataFrame 2 常用操作2.1 创建 Excel&#xff1a;to_excel()2.2 读取 Excel&#xff1a;read_excel()2.2.1 header&#xff1a;标题的行索引2.2.2 index_col&#xff1a;索引列2.2.3 dtype&#xff1a;数据类型2.2.4 skiprows&#xff1a;跳过的行…

MySQL——表的内外连接

目录 一.内连接 二.外连接 1.左外连接 2.右外连接 一.内连接 表的连接分为内连和外连 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;我们前面学习的查询都是内连接&#xff0c;也是在开发过程中使用的最多的连接查询。 语法&#xff1a; s…

入侵检测(HCIP)

目录 一、渗透流程 二、入侵检测 1、入侵检测原理 2、入侵检测系统结构 3、入侵防御系统 三、恶意代码 1、恶意代码概念&#xff1a; 2、恶意代码命名&#xff1a; 3、恶意代码按传播方式分类&#xff1a; 4、恶意代码按照功能分类&#xff1a; 5、恶意代码传播途径…

uni-app page新建以及page外观配置

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

ArcGIS高程点生成等高线

基本步骤&#xff1a;数据清洗→创建TIN→TIN转栅格→等值线→平滑线。 1.&#xff08;重要&#xff09;数据清理&#xff1a;删除高程点中的高程异常值数据。 2.创建TIN:系统工具→3D Analyst Tools→数据管理→TIN→创建TIN&#xff08;可直接搜索工具TIN&#xff09;。 单击…

如何进行快照管理

目录 快照管理 手动创建快照 自动创建快照 快照管理 快照管理 传统的物理服务器&#xff0c;为了确保服务器中数据的安全&#xff0c;需要你自行定制备份策略&#xff0c;如果备份到服务器本地&#xff0c;如果存储损坏&#xff0c;备份会同正常数据一起丢失。也就是说需要…

从零构建tomcat环境

一、官网构建 1.1 下载 一般来说对于开源软件都有自己的官方网站&#xff0c;并且会附上使用文档以及一些特性和二次构建的方法&#xff0c;那么我们首先的话需要从官网或者tomcat上下载到我们需要的源码包。下载地址&#xff1a;官网、Github。 这里需要声明一下&#xff…

计算机毕业设计------SSM水果蔬菜商城批发网站

项目介绍 本项目分为前后台&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,管理员管理,网站用户管理,新闻公告管理,果蔬类型管理,城市信息管理,配货点管理,果蔬商品管理,果蔬订单管理,果蔬评价管理…

vivo手机怎样录屏?轻松录制精彩瞬间

“vivo手机怎样录屏呀&#xff1f;买了最新款的vivo手机&#xff0c;感觉功能挺齐全的&#xff0c;最近玩游戏的时候&#xff0c;突然想要录屏&#xff0c;但是怎么都找不到&#xff0c;就想问问大家&#xff0c;vivo手机录屏在哪里呀&#xff1f;” 智能手机已经成为我们生活…

【Java动态代理如何实现】

✅Java动态代理如何实现 ✅JDK动态代理和Cglib动态代理的区别 ✅拓展知识仓✅静态代理和动态代理的区别✅动态代理的用途✅Spring AOP的实现方式&#x1f4d1;JDK 动态代理的代码段&#x1f4d1;Cglib动态代理的代码块 ✅注意事项&#xff1a; 在Java中&#xff0c;实现动态代理…

从git上拉取代码---步骤

1、先进入gitlab地址 2、git clone 地址.git 3、cd 路径 4、git checkout dev 5、git checkout -b 自己的分支 &#xff08;创建自己的分支&#xff09;

Visual Studio2022配置ReSharper C++ 常用设置

如需安装免费的可以在下面留言&#xff0c;看到即回复 文章目录 Visual Studio2022配置ReSharper C 常用设置配置Visual Studio2022&#xff0c;使其能够按回车进行补全配置ReSharper C 设置自动弹出配置ReSharper C 的快捷键ReSharper C 去掉注释拼写使用中文注释 如何关闭新版…

SpringBoot整合jwt(小白入门)

本文项目所用版本为&#xff1a; https://blog.csdn.net/weixin_39570751/article/details/133386557 代码仓库: https://gitee.com/skyblue0678/springboot-demo 目录 什么是JWT JWT依赖 写一个jwt工具类 测试一下jwt 优化&#xff1a;将过期时间配置在文件中 答疑&…