表达式求值(中序遍历,)

news2025/1/16 17:55:45

 题目描述:


 分析:

此题是acwing的一个模板例题,利用中缀遍历解决,即可。

思路:

首先我们先了解一下什么是树的中序遍历?

中序遍历是 二叉树遍历 的一种,也叫做 中根遍历 、中序周游。 在二叉树中,中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。

如果有不了解中序遍历的小伙伴可以看一下这篇大佬文章:看懂二叉树的三种遍历_二叉树遍历的三种方法-CSDN博客

再来看一下这个题

“假设”我们有一颗二叉树,它的叶子结点是数字,其它结点(根节点)是运算符
这颗二叉树自根节点至叶子结点运算符的优先级逐级递增,也即根节点的优先级最低
 所以我们只需要将左右子树结果计算出来后,再根据根节点计算最终结点即可。

人为去建立一颗这样的树很麻烦,我们可以用栈模拟这样的一个过程。
 我们发现,想要计算某个结点的运算符,必要条件是左右子树都已经计算完。
比如:(1+1)*(2+2)显然由于括号的存在,此处‘’的优先级要低于此处的‘+’,我们要计算‘’需要先计算两边的‘+’。 

如图:

我们应该如何判断一个结点的左右子树已经遍历完? 

由于我们”假设“,存在的这棵树根节点的运算符优先级最低,所以这颗树从底部往上走,运算符的优先级就越低,所以当我们遇到当前运算符的优先级小于等于上一个运算符时,该结点的左右子树已经计算完。该结点的左右子树已经计算完。也就是这句话:while(!op.empty()&&pr[x]<=pr[op.top()]) eval();
在入栈前将栈内优先级更高的运算符计算完再入栈

另外因为括号无视优先级,需要优先计算括号内的数,那么我们在遇到‘)’时可以直接将栈内的数从后向前计算出来
 (在入栈时已经保证了优先级自后向前升高),直到遇到‘(’停止。
 这样,这棵树就完美的用栈模拟出来了。

解释如下图

如图: 

以上话术来源于acwing的评论区一位大佬给出,我总结一下。 


实现: 

(1)双栈,一个操作数栈,一个运算符栈;

(2)运算符优先级,栈顶运算符,和,即将入栈的运算符的优先级比较:

如果栈顶的运算符优先级低,新运算符直接入栈

如果栈顶的运算符优先级高,先出栈计算,新运算符再入栈

 

 出栈最终结果是63

以上面的图片来源于acwing的题解 ,思路很清晰~

AcWing 3302. 表达式求值:多图讲解运算符优先级+详细代码注释 - AcWing


例题:

AC代码: 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<unordered_map>

using namespace std;

stack<int> num;
stack<char> op;

//计算加减乘除函数
void eval()
{
    //数第二个数(但是实则是栈顶元素),方便后面做除法和减法
    //因为除法和减法,两个数不能换位置
    auto num2 = num.top();
    num.pop(); //出栈
    //数第一个数(但是实则是栈顶元素的下面一个)
    auto num1 = num.top();
    num.pop(); //出栈
    //运算符号
    auto c = op.top();
    op.pop();
    int x = 0;
    if(c == '+') x = num1 + num2;
    else if(c == '-') x = num1 - num2;
    else if(c == '*')x = num1 * num2;
    else x = num1 / num2;
    num.push(x); //计算结果入栈。
}


int main()
{
    //符号的等级
    unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
    string str;
    cin >> str;
    for(int i=0;i<str.size();i++)
    {
        auto c = str[i];
        //判断一下c是否为数字(isdigit函数)
        if(isdigit(c))
        {
            int x = 0,j = i;
            //双指针算法
            while(j < str.size() && isdigit(str[j]))
            {
                //算下一数字位数,例如:1111*22+1
                x = x * 10 + (str[j++] - '0');
            }
            i = j - 1;
            num.push(x);
        }
        else if(c == '(') //判断是否是左括号
        {
            op.push(c); //左括号直接入栈
        }
        else if(c == ')')
        {
            while(op.size() && op.top()!='(') eval();
            op.pop();
        }
        else
        {
            //如果栈顶运算符优先级较高,先操作栈顶元素再入栈
            while(op.size() && pr[op.top()] >= pr[c]) eval();
            //否则直接入栈
            op.push(c);
        }
    }
    //把没有操作完的运算符操作一遍
    while(op.size()) eval();
    //栈顶元素为最终答案
    cout << num.top() << endl;
    return 0;
}

 while (op.size() && pr[op.top()] >= pr[c]) eval(); 这里是while而不是if的原因

假如表达式为2-2*3+1,直到2-2*3都没有运算,遇到+的时候,先运算了2*3,还剩2-6
如果是if的话,就会把+和1入栈,栈里成了2-6+1,会先运算栈顶的6+1,再运算2-7,最终运算错误。
而如果是while,则会先运算2-6,再运算-4+1,运算正确。

思想就是当前树的子树都运算完了,再运算当前树的根节点

如下图:

如图: 


总结:

上述大部分都来源于acwing的评论区和题解,图片有的为本人所画,如有错误欢迎指出。

我的理解就是,本题采用去用一棵树的中序遍历去模拟此题,然后去用双栈实现。

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

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

相关文章

重头戏:盒子模型(box-model)

盒子模型(box-model): CSS处理网页时,他认为每一个标签都包含在一个不可见的盒子里面,如果我们将所有的标签都想象成盒子,那么我们对网页的布局就相当于是拜访盒子,我们只需要将相应的盒子摆放在网页中相应的位置就可以完成布局 盒子模型: 一个盒子我们往往会分成: 内容区(…

无法启动报,To install it, you can run: npm install --save @/components/iFrame/index

运行的过程中后台报错 npm install --save /components/iFrame/index&#xff0c;以为是安装三方依赖错误&#xff0c;经过多次重装node_modules依然没有用。 没办法&#xff0c;只能在项目中搜索 components/iFrame/index这个文件。。突然醒悟。。。 有时候&#xff0c;犯迷…

I.MX6ULL_Linux_驱动篇(54)linux 块设备驱动

前面我们都是在学习字符设备驱动&#xff0c;本章我们来学习一下块设备驱动框架&#xff0c;块设备驱动是Linux 三大驱动类型之一。块设备驱动要远比字符设备驱动复杂得多&#xff0c;不同类型的存储设备又对应不同的驱动子系统&#xff0c;本章我们重点学习一下块设备相关驱动…

CSS块元素,CSS的伪类和伪元素

学习建议 在你开始入手学习前&#xff0c;有一些小的建议。根据我自己学习的经验发现&#xff0c;这些建议在现在乃至我以后的岗位生涯里都是有很大帮助的。还有就是开始学习前&#xff0c;建议可以先花几天时间&#xff0c;查找一些如何入门的文章&#xff0c;通过对许多文章…

linux系统Jenkins工具配置webhook自动部署

Jenkins工具webhook自动部署 webhook自动部署webhook的意义操作流程jenkins页面操作gitlab页面操作 webhook自动部署 webhook的意义 自动化部署&#xff1a;Webhook 可以在代码提交、合并请求或其他特定事件发生时自动触发 Jenkins 构建和部署任务&#xff0c;从而实现自动化…

CSS的标准文档流,web设计与开发

CSS篇 让一个元素水平垂直居中&#xff0c;到底有多少种方案&#xff1f;浮动布局的优点&#xff0c;缺点&#xff1f;清除浮动的方式&#xff1f;使用display:inline-block会产生的问题&#xff1f;解决方法&#xff1f;布局题&#xff1a;div垂直居中&#xff0c;左右10px&a…

如何关闭远程桌面连接

远程桌面连接是一种方便的技术&#xff0c;可以让用户通过网络远程访问其他计算机的桌面界面。有时候我们可能需要关闭这个连接。本文将向你介绍如何关闭远程桌面连接。 关闭远程桌面连接的步骤 要关闭远程桌面连接&#xff0c;按照以下步骤操作&#xff1a; 打开远程桌面连接…

机器学习-面经(part6、集成学习)

10 集成学习 定义:通过结合多个学习器(例如同种算法但是参数不同,或者不同算法),一般会获得比任意单个学习器都要好的性能,尤其是在这些学习器都是"弱学习器"的时候提升效果会很明显。 10.1 Boosting(提升法) 可以用于回归和分类 问题,它每一…

关于出国留学和考研比较----以本人双非跨考计算机为例

文章目录 中心论点国内就业现状勿让旧认知害了自己那出国留学真的一无是处了吗?1. 藤校仍旧是具有极高价值2. 时间成本低3. 研究生一定比单纯的本科找工作强!4. 很多人说出国读博好,可以无脑入,真是这样吗? 中心论点 如果在选择出国留学还是国内考研的最终核心诉求都是有更好…

Luajit 2023移动版本编译 v2.1.ROLLING

文章顶部有编好的 2.1.ROLLING 2023/08/21版本源码 Android 64 和 iOS 64 luajit 目前最新的源码tag版本为 v2.1.ROLLING on Aug 21, 2023应该是修正了很多bug, 我是出现下面问题才编的. cocos2dx-lua 游戏 黑屏 并报错: [LUA ERROR] bad light userdata pointer 编…

CSS盒模型居中方法,web小程序开发工具

面试知识点 主要内容包括html&#xff0c;css&#xff0c;前端基础&#xff0c;前端核心&#xff0c;前端进阶&#xff0c;移动端开发&#xff0c;计算机基础&#xff0c;算法与数据结构&#xff0c;设计模式&#xff0c;项目等等。 html 1.浏览器页面有哪三层构成&#xff0c…

在Vue中搭建Three.js环境(超详细、保姆级),创建场景、相机、渲染器《一》

目录 Three.js简介创建vue项目引入Three.js实际操作环节文件目录创建初始化场景、相机 Three.js简介 Three.js 是一款基于 WebGL的 JavaScript 3D 库&#xff0c;它封装了 WebGL API&#xff0c;为开发者提供了简单易用的 API 来在 Web 浏览器中展示 3D 图形。Three.js 提供了…

【C#杂谈】在 .NET Framework 中使用新的C#语言特性

前排提示&#xff1a;提出一个可以让 [^1] 这中语法可以在.NET Framework运行时中使用的方法 众所都周知&#xff0c;.NET Framework&#xff08;以下简称 .NF&#xff09;作为一个被微软官方确认不在继续发布新特性的运行时&#xff0c;它所对应的C#语言版本被&#xff08;官方…

Unity使用UnityWebRequest读取音频长度不对的解决方法

在开发的过程中碰到这样一个问题&#xff0c;有的音频文件通过UnityWebRequest读取出来后&#xff0c;AudioClip的Length会不对&#xff0c;比如本身有7秒&#xff0c;读出来只有3秒。代码如下&#xff1a; IEnumerator TestEnumerator() {UnityWebRequest www UnityWebReque…

BERT学习【BERT的例子以及作用】

一、case 1.case1 多输入单输出。通过输入一个句子&#xff08;sequence&#xff09;&#xff0c;然后输出一个句子的分类&#xff08;这个句子是正向还是负向&#xff09;。将句子输入BERT&#xff0c;然后通过softmax输出分类。 2.case2 多输入多输出。输入一个句子&…

专业的安全数据交换系统,如何进行网间数据安全交换?

网络隔离是企业网络安全管理的重要组成部分&#xff0c;它有助于提高网络的整体安全性&#xff0c;保护企业资产和客户数据&#xff0c;同时满足法规合规要求。很多企业为了防止内部核心数据泄露&#xff0c;都实施了网络隔离&#xff0c;比如划分成内网、外网&#xff0c;有的…

安装R语言,完整教程

安装R语言&#xff0c;完整教程 介绍特点 应用场景和用户对象安装教程下载地址安装打开软件 介绍 R语言是一种用于统计分析和数据可视化的编程语言&#xff0c;广泛应用于学术研究、数据科学、商业分析等领域。它由新西兰奥克兰大学的Ross Ihaka和Robert Gentleman于1995年开发…

Ps:色阶

色阶 Levels命令用于改善图像的对比度和调整亮度/暗度平衡&#xff0c;通过操作图像的直方图来精细调整图像的阴影、中间调和高光。 Ps菜单&#xff1a;图像/调整/色阶 Adjustments/Levels 快捷键&#xff1a;Ctrl L Ps菜单&#xff1a;图层/新建调整图层/色阶 New Adjustment…

Acwing 周赛145 解题报告 | 珂学家 | 贪心构造

前言 整体评价 VP了这场比赛&#xff0c;偏简单吧。T3是道贪心构造题&#xff0c;卡语言&#xff0c;因为题和数都是从CF拿来的。 A. 平均成绩 思路: 模拟 这边有个小技巧&#xff0c;就是规避浮点运算。 可以左右侧都乘以3。 #include <bits/stdc.h>using namespac…

稀碎从零算法笔记Day9-LeetCode:最后一个单词的长度

题型&#xff1a;字符串、反转字符串 链接:58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述&#xff08;红字为笔者添加&#xff09; 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔…