中后缀表达式

news2025/2/7 21:48:50

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

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.coloradmin.cn/o/1336290.html

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

相关文章

【深度学习-目标检测】03 - Faster R-CNN 论文学习与总结

论文地址&#xff1a;Faster R-CNN: Towards Real-Time ObjectDetection with Region Proposal Networks 论文学习 1. 摘要与引言 研究背景与挑战&#xff1a;当前最先进的目标检测网络依赖于 区域提议&#xff08;Region Proposals&#xff09;来假设目标的位置&#xff0c…

计算机服务器中了halo勒索病毒如何解密,halo勒索病毒解密数据恢复

计算机技术的不断发展&#xff0c;为企业的生产运营提供了极大便利&#xff0c;但也为网络安全埋下隐患&#xff0c;网络上的勒索病毒种类也在不断增加&#xff0c;给企业的数据安全带来了严重威胁。近日&#xff0c;云天数据恢复中心接到许多企业的求助&#xff0c;企业的计算…

HarmonyOS应用程序包-(上)

应用程序包-(上) 1.应用程序包概述 用户应用程序泛指运行在设备的操作系统之上&#xff0c;为用户提供特定服务的程序&#xff0c;简称“应用”。一个应用所对应的软件包文件&#xff0c;称为“应用程序包”。 HarmonyOS提供了应用程序包开发、安装、查询、更新、卸载的管理…

【Spring实战】06 ApplicationRunner

文章目录 1. 简介2. 使用1&#xff09;单个 ApplicationRunner2&#xff09;获取命令行参数3&#xff09;多个 ApplicationRunner 3. 优点4. 缺点总结 ApplicationRunner 是 Spring Boot 提供的一个接口&#xff0c;与 CommandLineRunner 类似&#xff0c;用于在 Spring Boot 应…

Linux文件编程

目录 1、Linux系统提供的文件编程API 1.1打开文件&#xff1a;open 1.2创建文件creat函数 1.3写入文件write函数 1.4读取文件read函数 1.5文件光标位置lseek函数 2、另外一组文件编程API 2.1文件打开函数fopen 2.2读文件函数fread 2.3写文件函数fwrite 2.4文件光标位…

jquery Tab切换,CSS3制作发光字

jquery Tab切换&#xff0c;CSS3制作发光字 代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta ht…

App应用如何在应用市场获得更多下载量?

App的转化率至关重要&#xff0c;App如何获得更多用户&#xff0c;提高应用的下载量&#xff1f; 据 Apple 称&#xff0c;每周有 6.5亿访问者访问应用商店&#xff0c;77%的应用下载来自 iOS 应用商店的自然搜索。随着 Apple 默认关闭了IDFA&#xff0c;自然搜索比以往任何时…

Exploring the Limits of Masked Visual Representation Learning at Scale论文笔记

论文名称&#xff1a;EVA: Exploring the Limits of Masked Visual Representation Learning at Scale 发表时间&#xff1a;CVPR2023 作者及组织&#xff1a;北京人工智能研究院&#xff1b;华中科技大学&#xff1b;浙江大学&#xff1b;北京理工大学 GitHub&#xff1a;http…

OpenCV之图像匹配与定位

利用图像特征的keypoints和descriptor来实现图像的匹配与定位。图像匹配算法主要有暴力匹配和FLANN匹配&#xff0c;而图像定位是通过图像匹配结果来反向查询它们在目标图片中的具体坐标位置。 以QQ登录界面为例&#xff0c;将整个QQ登录界面保存为QQ.png文件&#xff0c;QQ登…

百度Apollo五步入门自动驾驶:Dreamview与离线数据包分析(文末赠送apollo周边)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 粉丝福利活动 ✅参与方式&#xff1a;通过连接报名观看课程&#xff0c;即可免费获取精美周边 ⛳️活动链接&#xf…

Kind创建k8s - JAVA操作控制

kind 简介kind 架构安装 Kind (必备工具)docker官网kubectl官网kind官网校验安装结果 关于kind 命令 安装一个集群查看当前 Kubernetes 集群中的节点信息。查看当前命名空间下中的Pod&#xff08;容器实例&#xff09;的信息。使用 kind create cluster 安装&#xff0c;关于安…

分布式下有哪些好用的监控组件?

在之前的内容中&#xff0c;分析了分布式系统下的线上服务监控的常用指标&#xff0c;那么在实际开发中&#xff0c;如何收集各个监控指标呢&#xff1f;线上出现告警之后&#xff0c;又如何快速处理呢&#xff1f;本文我们就来看下这两个问题。 常用监控组件 目前分布式系统…

深入剖析LinkedList:揭秘底层原理

文章目录 一、 概述LinkedList1.1 LinkedList简介1.2 LinkedList的优点和缺点 二、 LinkedList数据结构分析2.1 Node节点结构体解析2.2 LinkedList实现了双向链表的原因2.3 LinkedList如何实现了链表的基本操作&#xff08;增删改查&#xff09;2.4 LinkedList的遍历方式 三、 …

matlab设置colorbar标题的两种方式

%% 第一种 figure; A rand(3,4,3); A1 A(:,:,1); A2 A(:,:,2); A3 A(:,:,3); contourf(A1,A2,A3,30); colormap(jet);colorbar; my_handlecolorbar; my_handle.Label.String depth/km; my_handle.Label.FontSize 15;%% 第二种 figure; A rand(3,4,3); A1 A(:,:,1); A2 …

排序算法--------计数排序

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

【VS】NETSDK1045 当前 .NET SDK 不支持将 .NET 6.0 设置为目标。

问题描述 报错 NETSDK1045 严重性代码说明项目文件行禁止显示状态错误NETSDK1045当前 .NET SDK 不支持将 .NET 6.0 设置为目标。请将 .NET 5.0 或更低版本设置为目标&#xff0c;或使用支持 .NET 6.0 的 .NET SDK 版本。RCSoftDrawMicrosoft.NET.TargetFrameworkInference.ta…

2024年科技盛宴“上海智博会·上海软博会”招商工作接近尾声

2024年上海智博会和上海软博会即将于3月份在上海跨国采购会展中心盛大召开。作为全球科技和软件行业的盛会&#xff0c;这两大展会汇集了业界顶尖的企业、创新技术和前瞻思想&#xff0c;吸引了来自世界各地的专业人士和参展商。 今年的展会将一如既往地为大家呈现最前沿的科技…

TypeScript下载安装,编译运行

TypeScript是拥有类型的JavaScript超集&#xff0c;它可以编译成普通、干净、完整的JavaScript代码。 简单理解&#xff1a;TypeScript就是加强版的JavaScript。 TypeScript最终会被编译成JavaScript代码&#xff0c;那么我们必然需要对应的编译环境 环境搭建前提&#xff1a…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)Dispatcher模块的实现思路和定义

&#xff08;四&#xff09;Dispatcher模块的实现思路 关于dispatcher&#xff0c;它应该是反应堆模型里边的核心组成部分&#xff0c;因为如果说这个反应堆模型里边有事件需要处理&#xff0c;或者说有事件需要检测&#xff0c;那么是需要通过这个poll、epoll 或者 select来完…

C# 初识System.IO.Pipelines

写在前面 在进一步了解Socket粘包分包的过程中&#xff0c;了解到了.NET 中的 System.IO.Pipelines&#xff0c;可以更优雅高效的解决这个问题&#xff1b;先跟随官方的示例做个初步的认识。 System.IO.Pipelines 是一个库&#xff0c;旨在使在 .NET 中执行高性能 I/O 更加容…