03-3.3.2_1 栈在表达式求值中的应用(上)

  • 👋 Hi, I’m @Beast Cheng
  • 👀 I’m interested in photography, hiking, landscape…
  • 🌱 I’m currently learning python, javascript, kotlin…
  • 📫 How to reach me --> 458290771@qq.com

喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑‍💻
此外,《程序员必备技能》专栏和《程序员必备工具》专栏(该专栏暂未开设)日后会逐步更新,感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏

引言

大家熟悉的算数表达式

( ( 15 ÷ ( 7 − ( 1 + 1 ) ) ) × 3 ) − ( 2 + ( 1 + 1 ) ) ((15÷(7-(1+1)))×3)-(2+(1+1)) ((15÷(7(1+1)))×3)(2+(1+1))
在我们熟悉的算数表达式中,由三个部分组成:

  1. 操作数:如1, 2, 3, 4, 5这些
  2. 运算符:如加减乘除这些
  3. 界限符:如括号

波兰数学家的灵感

灵感:可以不用界限符也能无歧义地表达运算顺序
Reverse Polish notation(逆波兰表达式 = 后缀表达式)
Polish notation(波兰表达式 = 前缀表达式)

三种算数表达式

(1)中缀表达式

运算符在两个操作数中间:
a + b a + b a+b
a + b − c a+b-c a+bc
a + b − c ∗ d a+b-c*d a+bcd

(2)后缀表达式

运算符在两个操作数后面:
a b + a b + ab+
a b + c − ab+c- ab+c 或者也可以先算 b − c b-c bc,那么结果就是: a b c − + abc-+ abc+
a b + c d ∗ − ab+cd*- ab+cd
要注意操作数的左右顺序

(3)前缀表达式

运算符在两个操作数的前面:
+ a b + a b +ab
− + a b c -+abc +abc,类似的,也可以写成别的形式
− + a b ∗ c d -+ab*cd +abcd

后缀表达式相关考点

(1)中缀表达式转后缀表达式

中缀转后缀的手算方法

  1. 确定中缀表达式中各个运算符的运算顺序
  2. 选择下一个运算符,按照「左操作数 右操作数 运算符」的方式组合成一个新的操作数
  3. 如果还有运算符没有被处理,就继续执行步骤 2
    根据以上步骤,在引言中的算数表达式: ( ( 15 ÷ ( 7 − ( 1 + 1 ) ) ) × 3 ) − ( 2 + ( 1 + 1 ) ) ((15÷(7-(1+1)))×3)-(2+(1+1)) ((15÷(7(1+1)))×3)(2+(1+1))
    就可以写成: ( 3 ( 15 ( 7 ( 11 + ) − ) ÷ ) × ) ( 2 ( 11 + ) + ) − (3(15(7(11+)-)÷)×)(2(11+)+)- (3(15(7(11+))÷)×)(2(11+)+)

上面算数表达式中的括号应该是去掉的
加在上面是为了便于理解
括号中的 11+,不是 11,而是两个 1

再举一个例子: A + B × ( C − D ) − E ÷ F A+B×(C-D)-E÷F A+B×(CD)E÷F
转换为后缀表达式就应该是: A B C D − × + E F ÷ − ABCD-×+EF÷- ABCD×+EF÷

运算顺序不唯一
因此对应的后缀表达式也不唯一

练习:写出 A + B × ( C − D ) − E ÷ F A+B×(C-D)-E÷F A+B×(CD)E÷F 的另一种后缀表达式形式
答案: A B C D − × E F ÷ − + ABCD-×EF÷-+ ABCD×EF÷+

客观来说,两种形式都是正确的
只是“机算”的结果是前者

那么如何才能写出更精确的后缀表达式呢?
使用 “左优先原则”:只要左边的运算符能够先运算,就先计算左边的
这样可以保证运算顺序唯一
举例: A + B − C × D ÷ E + F A+B-C×D÷E+F A+BC×D÷E+F
转换后结果: A B + C D × E ÷ − F + AB+CD×E÷-F+ AB+CD×E÷F+

(2)后缀表达式求值

后缀表达式的手算方法
从左往右扫描,每遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合体为一个操作数
注意:两个操作数的运算顺序

用计算机机算后缀表达式

用栈实现后缀表达式的计算:

  1. 从左往右扫描下一个元素,直到处理完所有元素
  2. 若扫描到操作数则压入栈,并回到步骤 1;否则执行步骤 3
  3. 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,回到步骤 1

需要注意的是:先出栈的是右操作数
若表达式合法,则最后栈中只会留下一个元素,也就是最终结果

具体代码实现

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <string.h> #define MAX 100 // 定义栈的最大长度 typedef struct {int data[MAX]; int top; 
} IntStack; // 初始化整数栈 
void InitIntStack(IntStack *S) {S->top = -1; 
} // 判断整数栈是否为空 
int IntStackEmpty(IntStack S) {return S.top == -1; 
} // 整数元素入栈 
void IntPush(IntStack *S, int x) {S->data[++S->top] = x; 
} // 整数元素出栈 
int IntPop(IntStack *S) {if (IntStackEmpty(*S)) {return 0; // 栈空返回0 } return S->data[S->top--]; 
} // 计算后缀表达式的值 
int evaluatePostfix(const char* postfix) {IntStack S;InitIntStack(&S); int i = 0, num1, num2, result; char ch; while ((ch = postfix[i++]) != '\0') {if (isdigit(ch)) { int num = 0; while (isdigit(ch)) { num = num * 10 + (ch - '0'); ch = postfix[i++]; } IntPush(&S, num); } else if (ch == ' ') { continue; // 忽略空格 } else { num2 = IntPop(&S); num1 = IntPop(&S); switch (ch) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': result = num1 / num2; break; } IntPush(&S, result); } } return IntPop(&S); 
} int main() { // 给定的后缀表达式 const char postfix[] = "15 7 1 1 + - / 3 * 2 1 1 + + -";int result = evaluatePostfix(postfix); printf("计算结果: %d\n", result); return 0; 
}

代码解释

  • const char* postfix 的意思?
    • const 表示这个字符串指针指向的数据(字符串)是不可变的,即你不能通过这个指针修改字符串的内容。
    • char* 表示这个指针指向的是一个字符(char)数组(或者说是一个 C 风格的字符串)。
    • postfix 是这个指针的变量名。
  • 哪里来的 isdigit 函数?
    • isdigit 是 C 标准库函数,定义在 <ctype.h> 头文件中。
      • 这个函数接受一个字符作为参数,判断是否是数字字符(‘0’-‘9’)
      • 如果是数字字符,返回非零值(通常为1),否则返回0
  • num = num * 10 + (ch - '0'); 是什么意思?
    • 这行代码用于将连续的字符数字转换成一个整数。考虑例子,同一个位置的ch是一个数字字符:
      • ch - '0' 将字符数字转换为对应的整数值。例如,‘4’ - ‘0’ 将得到整数 4。
      • num * 10 表示将之前的数向左移动一个十进制位,以便新的数字字符可以追加到末位。
      • 然后加上新的数字,这样可以将多位字符数字连接成一个完整的整数
      • 例如,处理字符串 “123”:
        • '1' - '0' = 1num = 0 * 10 + 1 => num = 1
        • '2' - '0' = 2num = 1 * 10 + 2 => num = 12
        • '3' - '0' = 3num = 12 * 10 + 3 => num = 123
  • ch = postfix[i++]; 是什么意思?
    • ch = postfix[i++]; 用来从字符串 postfix 中依次取得字符,并存储到 ch 变量中
      • postfix[i] 是字符串 postfix 的第 i 个字符
      • ch = postfix[i] 表示将这个字符赋值给变量 ch
      • i++ 是一个后缀自增操作,表示先使用 i 的当前值,然后再将 i 增加 1,以备下次使用

前缀表达式相关考点

(1)中缀表达式转前缀表达式

与中缀转后缀类似,不再过多赘述

(2)前缀表达式求值

手算

中缀转前缀手算方法

  1. 确定中缀表达式中各个运算符的运算顺序
  2. 选择下一个运算符,按照「运算符 左操作数 右操作数」的方式组合成一个新的操作数
  3. 如果还有运算符没被处理,就继续执行步骤 2

在这里使用的是右优先原则
只要右边的运算符能先计算,就先算右边

机算

用栈实现前缀表达式的计算:

  1. 从右往左扫描下一个元素,直到处理完所有元素
  2. 若扫描到操作数则压入栈,并回到步骤 1;否则执行步骤 3
  3. 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,回到步骤 1

注意:先出栈的是左操作数

知识回顾与重要考点

表达式求值问题

  • 概念:运算符、操作符、界限符(DIY概念:左操作数、右操作数)
  • 三种表达式
    • 中缀表达式:运算符在操作数中间
    • 后缀表达式(逆波兰式):运算符在操作数后面
    • 前缀表达式(波兰式):运算符在操作数前面
  • 后缀表达式考点
    • 中缀转后缀
      • 按左优先原则确定运算符的运算顺序
      • 根据确定的顺序,依次将各个运算符和与之相邻的两个操作数按规则合体
    • 后缀转中缀
      • 从左往右扫描,每遇到一个运算符,就按规则解体
    • 计算
      • 从左往右扫描,遇到操作数就入栈,遇到运算符则弹出两个栈顶元素运算后入栈(先弹出的是右操作数)
  • 前缀表达式
    • 中缀转前缀
      • 按右优先原则确定运算次序
      • 根据确定的次序,依次按规则合体
    • 计算
      • 从右往左扫描,遇到操作数入栈,遇到运算符就弹出两个栈顶元素运算后入栈(先弹出的是左操作数)

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

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

相关文章

跨机拷贝数据工具

1. rsync 支持断点续传单进程拷贝 典型命令 rsync -avurP src/dst/ 会将src目录下的内容&#xff08;不包括src目录&#xff09;全部同步到dst目录下

高效文件传输攻略:利用局域网共享实现极速数据同步

最近&#xff0c;我换了一台新电脑&#xff0c;面对两个电脑之间文件备份和传输的问题&#xff0c;感到十分头疼。经过多方了解&#xff0c;我发现可以在原电脑上设置共享文件&#xff0c;然后接收方从共享文件中接受即可&#xff0c;这样可以将局域网的带宽拉满&#xff0c;比…

智能硬件产品中常用的参数存储和管理方案

一、有哪些参数需要管理? 在智能硬件产品中,一般有三类数据需要存储并管理: 1. 系统设置数据 系统设置数据是指产品自身正常工作所依赖的一些参数。 这类数据的特点:只能在生产过程中修改,出厂后用户无权限修改。 比如:产品SN、产品密钥/token/license、传感器校准值…

✔️Vue基础+

✔️Vue基础 文章目录 ✔️Vue基础computed methods watchcomputed计算属性methods计算属性computed计算属性 VS methods方法计算属性的完整写法 watch侦听器&#xff08;监视器&#xff09;watch侦听器 Vue生命周期Vue生命周期钩子 工程化开发和脚手架脚手架Vue CLI 项目目录介…

Nvidia/算能 +FPGA+AI大算力边缘计算盒子:隧道和矿井绘图设备

RockMass 正在努力打入采矿业和隧道工程利基市场。 这家位于多伦多的初创公司正在利用 NVIDIA AI 开发一款绘图平台&#xff0c;帮助工程师评估矿井和施工中的隧道稳定性。 目前&#xff0c;作为安全预防措施&#xff0c;地质学家和工程师会站在离岩石五米远的地方&#xff0…

Lua移植到标准ANSI C环境

本文目录 1、引言2、环境准备2.1 源码下载2.2 项目构建环境准备 3、项目编译3.1 添加main.c3.2 Kconfig选择模块3.3 项目构建3.4 项目编译 4、运行 文章对应视频教程&#xff1a; 在下方喔 ~~~ 欢迎关注 点击图片或链接访问我的B站主页~~~ lau解释器移植与功能验证 1、引言 本…

01Linux的安装,时区,固定IP的配置

Linux系统的简介与安装 Linux简介 计算机是由硬件和软件所组成 硬件&#xff1a;计算机系统中由电子,机械和光电元件等组成的各种物理装置的总称软件&#xff1a;是用户和计算机硬件之间的接口和桥梁&#xff0c;用户通过软件与计算机进行交流(操作系统) 操作系统作为用户和…

java-集合使用 2

Vector 类 Vector 类是基于动态数组的数据结构实现的&#xff0c;与 ArrayList 类似&#xff0c;但它是线程安全的。Vector 类的主要特点如下&#xff1a; - 允许包含重复元素&#xff1b; - 允许使用 null 值&#xff1b; - 线程安全&#xff1b; - 查询速度快&#xff0c;但插…

Visual 怎么编程:一场视觉与逻辑的奇妙旅程

Visual 怎么编程&#xff1a;一场视觉与逻辑的奇妙旅程 编程&#xff0c;这一曾经看似高不可攀的技术领域&#xff0c;如今随着可视化编程工具的普及&#xff0c;已逐渐走入寻常百姓家。那么&#xff0c;Visual 怎么编程&#xff1f;本文将从四个方面、五个方面、六个方面和七…

WEB漏洞服务能提供哪些帮助

在数字化浪潮的推动下&#xff0c;Web应用程序已成为企业展示形象、提供服务、与用户进行交互的重要平台。然而&#xff0c;随着技术的飞速发展&#xff0c;Web应用程序中的安全漏洞也日益显现&#xff0c;成为网络安全的重大隐患。这些漏洞一旦被恶意攻击者利用&#xff0c;可…

【Vue】面经基础版-首页请求渲染

步骤分析 1.安装axios 2.看接口文档&#xff0c;确认请求方式&#xff0c;请求地址&#xff0c;请求参数 3.created中发送请求&#xff0c;获取数据&#xff0c;存储到data中 4.页面动态渲染 代码实现 1.安装axios yarn add axios npm i axios 2.接口文档 请求地址: …

Java 数据库连接(JDBC)的使用,包括连接数据库、执行SQL语句等

一、简介 Java Database Connectivity&#xff08;JDBC&#xff09;是Java应用程序与关系数据库进行交互的一种API。它提供了一组用于访问和操作数据库的标准接口&#xff0c;使开发人员能够使用Java代码执行数据库操作&#xff0c;如查询、插入、更新和删除等。 二、JDBC架构…

除留取余法构造散列表--c++【做题记录】

【题目描述】 用除留取余法构造散列表&#xff0c;输入序列并实现查找操作。 【算法】 哈希函数使用除留余数法 若已知整个哈希表的最大长度 m&#xff0c;可以取一个不大于 m 的数 p&#xff0c;然后对该关键字 key 做取余运算&#xff0c;即&#xff1a;H&#xff08;key&a…

gbase 扩容 集群数据同步 主备切换

问题&#xff1a; 问题1磁盘满 1.原本是100G的大小&#xff0c;我们实际还没接入真正业务&#xff0c;昨日空间满了&#xff0c;需要帮忙看下是什么原因导致磁盘满的吗 数据库是每天备份一次&#xff0c;是不是备份的太频繁&#xff0c;还是数据量的问题导致&#xff0c;需要…

[工具探索]富士mini90拍立得使用指南

文章目录 1. 基本功能介绍1.1 相机外观1.2 电池与胶片 2. 设置相机2.1 装入电池2.2 装入胶片 3. 拍摄模式3.1 标准模式3.2 儿童模式3.3 远景模式3.4 双重曝光模式3.5 Bulb&#xff08;B&#xff09;模式3.6 **派对模式**3.7 微距模式3.8 **亮度模式**3.9 **定时拍摄模式**3.10 …

Elastic Search(ES)Java 入门实操(2)搜索代码

上篇解释了 ES 的基本概念和分词器。Elastic Search &#xff08;ES&#xff09;Java 入门实操&#xff08;1&#xff09;下载安装、概念-CSDN博客 Elastic Search&#xff08;ES&#xff09;Java 入门实操&#xff08;3&#xff09;数据同步-CSDN博客 这篇主要演示 Java 整合…

React Hooks 封装可粘贴图片的输入框组件(wangeditor)

需求是需要一个文本框 但是可以支持右键或者ctrlv粘贴图片&#xff0c;原生js很麻烦&#xff0c;那不如用插件来实现吧~我这里用的wangeditor插件&#xff0c;初次写初次用&#xff0c;可能不太好&#xff0c;但目前是可以达到实现需求的一个效果啦&#xff01;后面再改进吧~ …

个位为0的数字-第13届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第81讲。 个位为0的数字&am…

秋招突击——算法打卡——6/6——复习{三数之和、考试最大困扰度}——快速新作{环形链表}

文章目录 复习最大考试困扰度三数之和——做的不好 新作环形链表实现代码 明天面试拼多多&#xff0c;因为今天面华为遇到了一个做过的题目&#xff0c;没做出来&#xff0c;关键是这个题目第一次做出来了&#xff0c;这次居然没有做出来&#xff0c;比较烦&#xff0c;所以今天…

光通信技术路线

自从1947年Bell实验室诞生第一支晶体管以来&#xff0c;芯片的尺寸大小和晶体管的集成度都遵循着“摩尔定律”进行飞速的发展。然而摩尔定律随着芯片尺寸的减小&#xff0c;进入到深亚微米或纳米量级之后&#xff0c;其发展也面临越来越严峻的挑战。近几年来虽然芯片上的晶体管…