算法练习-逆波兰表达式求值(思路+流程图+代码)

难度参考

        难度:中等

        分类:栈与队列

        难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。且所在课程未提供测试平台,故实现代码主要为自行测试的那种,以下内容均为个人笔记,旨在督促自己认真学习。

题目     

        根据逆波兰表示法,求表达式的值。
        有效的运算符包括+,·,*,/。每个运算对像可以是整数,也可以是另一个逆波兰表达式。

        说明:

        整数除法只保留整数部分。给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数
为0的情况。

        示例1:

        输入:["2","1","+","3","*门
        输出:9

        解释:该算式转化为常见的中缀算术表达式为:(2+1)*3)=9

        示例2:
        输入:["4","13","5","/","+"门

        输出:6
        解释:该算式转化为常见的中缀算术表达式为:(4+(13/5)=6

思路

        逆波兰表达式求解的一般思路是使用栈来存储操作数,然后遍历逆波兰表达式的每个元素,根据遇到的操作符进行相应的计算,并将结果重新入栈。遍历逆波兰表达式,并根据运算符进行相应的计算操作。

        具体步骤如下:

  1. 定义一个栈,用于存储中间结果。
  2. 遍历逆波兰表达式,对于每个元素:
    • 如果是数字,则将其转换为整数并压入栈中。
    • 如果是运算符,则从栈中取出两个数字进行相应的运算。将运算结果压入栈中。
  3. 遍历结束后,栈中存储的元素即为表达式的最终结果。

示例

        逆波兰表达式是一种不需要括号的数学表达式表示法,操作符位于操作数之后。

        主要思路是使用一个栈来存储操作数,并依次遍历输入的表达式。当遇到操作符时,从栈中弹出对应数量的操作数,并根据操作符进行相应的运算,将运算结果压入栈中。当遍历完整个表达式后,栈中只会剩下一个元素,即表达式的最终结果。

        举个例子来说明,假设我们要求解的逆波兰表达式是:2 1 + 3 *。我们依次遍历表达式中的每个字符:

  • 第一个字符 “2” 是一个操作数,我们直接将其压入栈中;
    "2", "1", "+", "3", "*"  //字符^st={2}                    //数字
  • 第二个字符 “1” 是另一个操作数,同样将其压入栈中;
    "2", "1", "+", "3", "*"  //字符^st={2, 1}                    //数字
  • 第三个字符 “+” 是一个加法操作符,此时栈中的顶部两个元素分别是 1 和 2,我们将它们弹出并做加法运算得到 3,将结果 3 压入栈中;
    "2", "1", "+", "3", "*"  //字符^st={3}                    //数字
  • 第四个字符 “3” 是一个操作数,将其压入栈中;
    "2", "1", "+", "3", "*"  //字符^st={3, 3}                    //数字
  • 最后一个字符 “*” 是一个乘法操作符,此时栈中的顶部两个元素分别是 3 和 3,弹出并做乘法运算得到 9,将结果 9 压入栈中。
    "2", "1", "+", "3", "*"  //字符^st={9}                    //数字

        最终栈中只剩下一个元素 9,即为表达式的结果。

梳理

        根据逆波兰表达式的性质,每当遇到一个操作符时,它前面的两个操作数已经被处理过并保存在栈中。所以,我们只需要从栈中弹出这两个操作数,根据操作符进行相应的运算,并将结果再次压入栈中。

  • 没有括号:逆波兰表达式的特点是不需要括号来标识优先级,因为操作数和操作符的顺序已经明确,不存在歧义。
  • 简化运算符的处理:由于操作符总是位于操作数之后,栈可以很方便地保存操作数。每当遇到一个操作符,只需要从栈中弹出所需的操作数进行运算,而不需要关心操作数之间的顺序或优先级。
  • 遍历一次求解:由于逆波兰表达式的特点,我们只需要遍历一次表达式即可求解,无需进行多次迭代或递归。

        总体来说,通过利用栈的先入后出(LIFO)的特性,将逆波兰表达式转化为了一种线性的、遍历一次即可求解的算法,从而实现了逆波兰表达式的求值。

代码

#include <iostream> // 包含输入输出流库,用于标准输入输出
#include <stack> // 包含栈库,用于存储操作数
#include <vector> // 包含向量库,用于存储输入的逆波兰表达式
#include <string> // 包含字符串库,用于操作字符串
#include <cstdlib> // 包含标准库,用于字符串转整数的函数using namespace std; // 使用标准命名空间int evalRPN(vector<string>& tokens) { // 定义了一个函数,用于计算逆波兰表达式的值,参数为存储表达式的向量stack<int> st; // 创建一个整型栈对象,用于存储操作数for (string& token : tokens) { // 遍历逆波兰表达式的每个元素if (token == "+") { // 如果当前元素为加号int num2 = st.top(); // 取出栈顶元素作为第二个操作数st.pop(); // 弹出栈顶元素int num1 = st.top(); // 取出新的栈顶元素作为第一个操作数st.pop(); // 弹出栈顶元素st.push(num1 + num2); // 将计算结果入栈} else if (token == "-") { // 如果当前元素为减号,逻辑同上int num2 = st.top();st.pop();int num1 = st.top();st.pop();st.push(num1 - num2);} else if (token == "*") { // 如果当前元素为乘号,逻辑同上int num2 = st.top();st.pop();int num1 = st.top();st.pop();st.push(num1 * num2);} else if (token == "/") { // 如果当前元素为除号,逻辑同上int num2 = st.top();st.pop();int num1 = st.top();st.pop();st.push(num1 / num2);} else { // 如果当前元素为数字st.push(stoi(token)); // 将字符串转换为整数后入栈}}return st.top(); // 返回栈中最终的结果
}int main() { // 主函数vector<string> tokens = {"2", "1", "+", "3", "*"}; // 创建一个存储逆波兰表达式的向量,其中元素为字符串int result = evalRPN(tokens); // 调用 evalRPN 函数计算表达式的值cout << result << endl; // 输出计算结果tokens = {"4", "13", "5", "/", "+"}; // 更新逆波兰表达式result = evalRPN(tokens); // 调用 evalRPN 函数计算表达式的值cout << result << endl; // 输出计算结果return 0; // 返回 0,表示正常结束程序
}

打卡

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

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

相关文章

Advanced CNN

文章目录 回顾Google NetInception1*1卷积Inception模块的实现网络构建完整代码 ResNet残差模块 Resedual Block残差网络的简单应用残差实现的代码 练习 回顾 这是一个简单的线性的卷积神经网络 然而有很多更为复杂的卷积神经网络。 Google Net Google Net 也叫Inception V…

Python Pandas 中的 case_when() 方法详解

概要 在 Python 数据分析中,Pandas 是一个强大的库,用于处理和分析数据。它提供了各种各样的方法和函数,使数据转换和操作变得更加容易。在本文中,将深入探讨 Pandas 中的 case_when() 方法,它可以用于条件性地创建新的列,类似于 SQL 中的 CASE WHEN 语句。我们将详细讨…

51单片机编程应用(C语言):独立按键

目录 1.独立按键介绍 2.独立按键控制LED亮灭 1.1按下时LED亮&#xff0c;松手LED灭&#xff08;按一次执行亮灭&#xff09; 1.2首先按下时无操作&#xff0c;松手时LED亮&#xff08;再按下无操作&#xff0c;所以LED亮&#xff09;&#xff0c;松手LED灭&#xff08;松手时…

Git系列---远程操作

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 引用 1.理解分布式版本控制…

Android 12.0 应用中监听系统收到的通知

Android 12.0 通知简介https://blog.csdn.net/Smile_729day/article/details/135502031?spm1001.2014.3001.5502 1. 需求 在系统内置应用中或者在第三方应用中,获取Android系统收到的通知的内容. 2. NotificationListenerService 接口 Android 系统预留了专门的API, 即 No…

【脑电信号处理与特征提取】P7-贾会宾:基于EEG/MEG信号的大尺度脑功能网络分析

基于EEG/MEG信号的大尺度脑功能网络分析 Q: 什么是基于EEG/MEG信号的大尺度脑功能网络分析&#xff1f; A: 基于脑电图&#xff08;EEG&#xff09;或脑磁图&#xff08;MEG&#xff09;信号的大尺度脑功能网络分析是一种研究大脑活动的方法&#xff0c;旨在探索脑区之间的功能…

075:vue+mapbox 利用高德地址逆转换,点击地图,弹出地址信息

第075个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中利用高德逆地理编码,点击地图,弹出某点坐标和地址信息。这里要仔细阅读高德地图的逆编码API,同时要注意的是,这种转换在中国很好用,到了欧美国家就不好使了。同时这个底图是天地图的图像和标记。 直接…

Qt 5.9.4 转 Qt 6.6.1 遇到的问题总结(三)

1.QSet: toList 中的toList 函数已不存在&#xff0c;遇到xx->toList改成直接用&#xff0c;如下&#xff1a; 2.开源QWT 图形库中QwtDial中的 setPenWidth 变成 setPenWidthF函数。 3.QDateTime 中无setTime_t 改为了setSecsSinceEpoch函数。 4.QRegExp 类已不存在 可以用Q…

vue3/vue2中自定义指令不可输入小数点.

import { directive } from vueconst noDecimal {mounted(el) {el.addEventListener(keypress, (e) > {if (e.key .) {e.preventDefault() }})} }// 使用自定义指令 directive(no-decimal, noDecimal)使用 标签上添加 v-no-decimal <el-input…

【微服务】Spring Boot集成ELK实用案例

推荐一款我一直在用国内很火的AI网站&#xff0c;包含GPT3.5/4.0、文心一言、通义千问、智谱AI等多个AI模型&#xff0c;支持PC、APP、VScode插件同步使用&#xff0c;点击链接跳转->ChatGPT4.0中文版 一、前言 在现代软件开发中&#xff0c;微服务架构已成为一种流行趋势。…

使用 axios 请求库,设置请求拦截

什么是 axios&#xff1f; 基于promise网络请求库&#xff0c;可以同构&#xff08;同一套代码可以运行在浏览器&#xff09;&#xff0c;在服务端&#xff0c;使用原生node.js的http模块&#xff0c;在客户端&#xff08;浏览器&#xff09;中&#xff0c;使用XMLHttpRequests…

轻松录制视频,WPS录屏功能全攻略

“有人知道wps怎么录屏吗&#xff1f;老师要求我们录制一段视频&#xff0c;是关于课堂教学的&#xff0c;可是我不会录制文档&#xff0c;眼看就快到提交的时间了&#xff0c;现在真的很着急&#xff0c;希望大家帮帮我&#xff01;” 随着信息技术的发展&#xff0c;录制屏幕…