数据结构与算法(二)——前缀、中缀、后缀表达式

一、前缀表达式(波兰表达式)

1.1、计算机求值

从右至左扫描表达式,遇到数字时,将数字压入堆栈。遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果

例如:
(3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6。针对前缀表达式求值步骤如下:
1)从右至左扫描,将 6、5、4、3压入堆栈;
2)遇到 + 运算符,因此弹出3和4(3为栈顶元素,4为次顶元素),计算出3+4的值,得 7,再将7入栈;
3)接下来是×运算符,因此弹出 7 和 5,计算出 7×5=35,将35入栈;
4)最后是 - 运算符,计算出 35-6 的值,即 29,由此得出最终结果。

二、中缀表达式

1)中缀表达式就是常见的运算符表达式,如 (3+4)×5-6
2)中缀表达式的求值是我们人类最熟悉的,但是对计算机来说缺不好操作。因此,在计算结果时,往往会将中缀表达式转成其他表达式来操作(一般转成后缀表达式)
中缀表达式 - 栈实现综合计算器

三、后缀表达式(逆波兰表达式)

1)后缀表达式又称 逆波兰表达式,与前缀表达式相近,只是运算符位于操作数之后;
2)举例说明:(3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 -
3)在这里插入图片描述

3.1、计算机求值

从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到操作符时,弹出栈顶的两个数,用运算符对它们做出相应的计算(次顶元素 和 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。

例如:
(3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 -。针对后缀表达式求值步骤如下:
1)从左至右扫描,将 3 和 4 压入堆栈;
2)遇到 + 运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得 7,再将7入栈;
3)接下来是×运算符,因此弹出 5 和 7,计算出 7×5=35,将35入栈;
4)将 6 入栈
5)最后是 - 运算符,计算出 35-6 的值,即 29,由此得出最终结果。

3.2、逆波兰计算器分析与实现

我们完成一个逆波兰计算器,要求完成如下任务:
1)输入一个逆波兰表达式(后缀表达式),使用栈(Stack), 计算其结果
2)支持小括号和多位数整数,因为这里我们主要讲的是数据结构,因此计算器进行简化,只支持对整数的计算。
3)思路分析
4)代码完成

package Algotithm.stackimport java.utilobject PolandNotation {def main(args: Array[String]): Unit = {//先定义一个逆波兰表达式val suffixExpression = "3 4 + 5 * 6 -"//思路//1.先将 suffixExpression => arrayList中//2.将arrayList传递给一个方法,遍历 配合栈完成计算val list = getListString(suffixExpression)println(list)val result = calculate(list)println(s"计算的结果时$result")}//将逆波兰表达式,依次将数据和运算符 放入到arrayList中def getListString(string: String): util.ArrayList[String] = {//将arrayList分割val strings = string.split(" ")val list = new util.ArrayList[String]()strings.foreach(elem => list.add(elem))list}//完成计算def calculate(list: util.ArrayList[String]): Int = {//创建栈,只需要一个栈即可val stack = new util.Stack[String]//遍历lslist.forEach(elem => {if (elem.matches("\\d+")) { //匹配的是多位数//入栈stack.push(elem)} else {//pop出两个数,并运算,再入栈val num2 = stack.pop().toIntval num1 = stack.pop().toIntval res = elem match {case "+" => num1 + num2case "-" => num1 - num2case "*" => num1 * num2case "/" => num1 / num2case _ => throw new Exception("运算符有误")}stack.push(res.toString)}})//最后留在stack中的就是运算结果stack.pop().toInt}
}

在这里插入图片描述

四、中缀转后缀表达式

具体步骤如下:
1)初始化两个栈:运算符栈s1和储存中间结果的栈s2;
2)从左至右扫描中缀表达式;
3)遇到操作数时,将其压s2;
4)遇到运算符时,比较其与s1栈顶运算符的优先级:
(1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;
(3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较;
5)遇到括号时:
(1) 如果是左括号“(”,则直接压入s1
(2) 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6)重复步骤2至5,直到表达式的最右边
7)将s1中剩余的运算符依次弹出并压入s2
8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

方法:将 中缀表达式转成对应的List

  //方法:将 中缀表达式转成对应的Listdef toInfixExpressionList(s: String): util.ArrayList[String] = {//定义一个list,存放中缀表达式 对应的内容val ls = new util.ArrayList[String]()var i = 0 //指针,用于遍历 lsvar str = "" //对多位数的拼接var c: Char = 0 //每遍历到一个字符,就放入到cwhile (i < s.length) {//如果c是一个非数字,需要加入到lsc = s.charAt(i)if (s.charAt(i) < 48 || s.charAt(i) > 57) {ls.add("" + s.charAt(i))i += 1} else { //如果是一个数,需要考虑多位数str = ""while (i < s.length && s.charAt(i) >= 48 && s.charAt(i) <= 57) {str += s.charAt(i)i += 1}ls.add(str)}}ls}

在这里插入图片描述

注意:在 while 中必须要加该判断,否则会下标越界异常。

定义优先级

class Operation {private val ADD = 1private val SUB = 1private val MUL = 2private val DIV = 2//返回对应的优先级数字def getValue(operation: String): Int = {val result = operation match {case "+" => ADDcase "-" => SUBcase "*" => MULcase "/" => DIVcase _ => 0}result}
}

中缀表达式list => 后缀表达式list

  //方法:将得到的中缀表达式list => 后缀表达式listdef parseSuffixExpressionList(ls: List[String]): util.ArrayList[String] = {//定义两个栈val s1 = new util.Stack[String] //符号栈//说明:因为s2在整个操作中没有pop,且后面还要逆序输出//因此不用stack,直接使用listval s2 = new util.ArrayList[String] //存储中间结果的list//遍历lsls.foreach(elem => {//如果是一个数,入s2if (elem.matches("\\d+")) {s2.add(elem)} else if (elem.equals("(")) {s1.push(elem)} else if (elem.equals(")")) {//如果是")",则依次弹出s1栈顶的运算符并压入s2,直到遇到"("while (!s1.peek().equals("(")) {s2.add(s1.pop())}s1.pop() //将 ( 弹出s1栈,消除括号} else {//当elem运算符优先级 ≤ s1栈顶运算符//比较优先级高低的方法while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(elem)) {s2.add(s1.pop())}//将elem压入栈中s1.push(elem)}})//将s1剩余的运算符依次弹出并加入s2while (s1.size() != 0) {s2.add(s1.pop())}s2  //因为是存放到list,因此按顺序输出就是后缀表达式}

主函数

def main(args: Array[String]): Unit = {//完成将一个中缀表达式转成后缀表达式的功能//说明//1.1+((2+3)*4)-5 => 1 2 3 + 4 * 5 -//2.因为直接对str操作不方便,因此先将 str 转成中缀的list//3.将得到的中缀表达式list => 后缀表达式listval expression = "1+((2+3)*4)-5"val infixExpressionList = toInfixExpressionList(expression)println(s"$infixExpressionList")val suffixExpressionList = parseSuffixExpressionList(infixExpressionList)println(s"对应的后缀表达式 => $suffixExpressionList")}

在这里插入图片描述

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

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

相关文章

Navicat导入Excel数据顺序变了

项目场景&#xff1a; Navicat导入Excel数据 问题描述 从Excel表格中导入数据到数据库中。但是&#xff0c;在导入的过程中&#xff0c;我们常会发现数据顺序出现了问题&#xff0c;导致数据错位&#xff0c;给数据的处理带来了极大的麻烦。 原因分析&#xff1a; 这个问题的…

mybatisplus配置拦截器实现保存加密,输出解密,模糊查询

前言&#xff1a;因公司需求需要把某些实体类的某些字段值进行加密保存&#xff0c;在查询时解密明文输出。现记录两种方式。 一、第一种方式&#xff1a; &#xff08;1&#xff09;使用TableField(typeHandler TypeHandler.class)注解自带的字段类型处理器&#xff0c;写一…

电脑死机的时候,CPU到底在做什么?

电脑死机&#xff0c;应该每个接触计算机的小伙伴都经历过吧。 尤其是早些年&#xff0c;电脑配置还没现在这么高的时候&#xff0c;多开几个重量级应用程序&#xff0c;死机就能如约而至&#xff0c;就算你把键盘上的CTRLALTDELETE按烂了&#xff0c;任务管理器也出不来&…

Mybatis-Genertor逆向工程

1、导入mybaties插件 <build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.2</version><dependencies><dependency>…

Error: svn: E155004: Run ‘svn cleanup‘ to remove locks

解决办法如下&#xff1a;点击settings 点击清除缓存按钮&#xff0c;然后再使用svn进行提交更新操作&#xff0c;但是可能还会有其它的错误&#xff0c;比如svn: E230001: Server SSL certificate verification failed&#xff0c;解决这个错误请参考我另一篇文章&#xff1a;…

博客系统(升级(Spring))(一)创建数据库,创建实例化对象,统一数据格式,统一报错信息

博客系统&#xff08;一&#xff09; 博客系统一、创建项目二、建立数据库结构链接服务器和数据库和Redis 三、创建实例化对象四、统一数据结构结构 五、统一报错信息 博客系统 博客系统是干什么的&#xff1f; CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博…

Python+Requests+Excel接口测试实战

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …

莫比乌斯召回系统介绍

当前召回系统只能召回相关性高的广告&#xff0c;但不能保证该广告变现能力强。莫比乌斯做了如下两点创新&#xff1a; 在召回阶段&#xff0c;引入CPM等业务指标作为召回依据在召回阶段&#xff0c;引入CTR模型&#xff0c;从而召回更多相关性高且变现能力强的广告 参考 百度…

基于Protege的知识建模实战

一.Protege简介、用途和特点 1.Protege简介 Protege是斯坦福大学医学院生物信息研究中心基于Java开发的本体编辑和本体开发工具&#xff0c;也是基于知识的编辑器&#xff0c;属于开放源代码软件。这个软件主要用于语义网中本体的构建&#xff0c;是语义网中本体构建的核心开发…

Elasticsearch:什么是生成式人工智能?

生成式人工智能定义 给学生的解释&#xff08;基本&#xff09;&#xff1a; 生成式人工智能是一种可以创造新的原创内容的技术&#xff0c;例如艺术、音乐、软件代码和写作。 当用户输入提示时&#xff0c;人工智能会根据从互联网上现有示例中学到的知识生成响应&#xff0c;…

linux安装Sentinal1.8.6

前言&#xff1a; 使用docker search sentinel-dashboard命令&#xff0c;发现docker中的镜像版本过低&#xff0c;由于要配合使用1.8.6&#xff0c;所以这里采用java后台运行sentinel1.8.6-jar的方式。 1、官网下载对应版本jar&#xff08;https://github.com/alibaba/Sentin…

MySQL间隙锁深入分析

概念 什么是间隙锁&#xff1f; MySQL的间隙锁&#xff08;gap lock&#xff09;是一种锁定相邻数据间隔的机制。 触发时机&#xff1f; 当使用SELECT…FOR UPDATE或UPDATE语句时&#xff0c;MySQL会获取一个范围锁&#xff0c;包括指定条件内的所有数据行&#xff0c;并且还…

rhcsa4 进程和SSH

tree命令。用于以树状结构显示目录和文件。通过运行 “tree” 命令可视化地查看文件系统中的目录结构。 tree / systemd是第一个系统进程&#xff08;pid1&#xff09;不启动&#xff0c;其他进程也没法启动&#xff0c; 用pstree查看进程树 我们可以看到所有进程都是syste…

设计模式之模板模式

文章目录 豆浆制作问题模板方法模式基本介绍模板方法模式原理类图对原理类图的说明-即(模板方法模式的角色及职责)模板方法模式解决豆浆制作问题模板方法模式的钩子方法模板方法模式的注意事项和细节 豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 制作豆浆的流程 选…

RocketMQ 消息传递模型

文章目录 0. 前言1. RocketMQ的消息传递模型1.1. 同步发送1.2. 异步发送1.3. 单向发送 2. RocketMQ的批量发送和消费2.1 批量发送2.2 批量消费2.3 Spring Boot集成RocketMQ官方starter 示例 3. 总结4. 参考文档5. 源码地址 0. 前言 RocketMQ 支持6种消息传递方式&#xff0c;我…

pyarmor 加密许可证的使用

一 pyarmor 许可证的用处 文档&#xff1a;5. 许可模式和许可证 — Pyarmor 8.3.6 文档 试用版本有如下的限制&#xff1a; 加密功能对脚本大小有限制&#xff0c;不能加密超过限制的大脚本。 混淆字符串功能在试用版中无法使用。 RFT 加密模式&#xff0c;BCC 加密模式在试…

解决java.io.IOException: Network error

解决java.io.IOException: Network error 解决java.io.IOException: Network error摘要引言正文1. 理解异常的根本原因2. 处理网络连接问题3. 处理连接超时4. 处理协议错误或不匹配5. 异常处理 总结参考资料 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&#…

24.Xaml ListView控件-----显示数据

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

电子信息工程专业课复习知识点总结:(四)信号与系统、数字信号处理

这次我不具体把所有概念写出来了&#xff0c;只针对一些面试中经常提问的重点问题。 第一章 信号与系统基本概念 这里提出一个信号与系统这本书的大纲&#xff1a;这本书研究的就是信号与系统的关系。 一.信号是什么&#xff1f; ①信息是自然世界中一种表现形式&#xff0…

pkg 打包 nodejs

一、先全局安装pkg npm i -g pkg 二、下载打包所需的 node-v16.16.0-linux-x64 和 node-v16.16.0-win-x64 下载地址&#xff0c;里面选择你需要的版本 三、放到pkg的缓存目录 windows&#xff1a;C:\Users\whh\.pkg-cache\v3.4&#xff0c;&#xff08;把whh替换为你的电脑…