当前位置: 首页 > news >正文

后缀表达式中缀表达式转后缀表达式

后缀表达式的计算机求值

计算规则

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

举例分析

例如: (3+4)*5-6 对应的后缀表达式就是 3 4 + 5 * 6 - , 针对后缀表达式求值步骤如下:

  1. 从左至右扫描,将3和4压入堆栈;
  2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
  3. 将5入栈;
  4. 接下来是*运算符,因此弹出5和7,计算出7*5=35,将35入栈;
  5. 将6入栈;
  6. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果
扫描元素s1(栈底->栈顶)说明
33数字,入栈
43 4数字,入栈
+7运算符,弹出栈顶的两个数,用运算符对它们做相应的计算(顺序:次顶元素 和 栈顶元素),并将结果入栈
57 5数字,入栈
*35运算符,弹出栈顶的两个数,用运算符对它们做相应的计算(顺序:次顶元素 和 栈顶元素),并将结果入栈
635 6数字,入栈
-29运算符,弹出栈顶的两个数,用运算符对它们做相应的计算(顺序:次顶元素 和 栈顶元素),并将结果入栈
29最终结果保存在操作数栈中

代码实现

import java.util.Stack;/*** @Author: * @Create: 2024-10-01 10:36* @Description:*  (3+4)×5-6  --> 3 4 + 5 × 6 -*/
public class 后缀表达式 {public static void main(String[] args) {String expression = "3 4 + 5 * 6 - ";String[] str = expression.split(" ");Stack<Integer> numStack = new Stack<>();int res = 0;for (String s : str) {if (s.matches("\\d+")) {numStack.push(Integer.parseInt(s));} else {Integer num1 = numStack.pop();Integer num2 = numStack.pop();switch (s) {case "+":res = num2 + num1;break;case "-":res = num2 - num1;break;case "*":res = num2 * num1;break;case "/":res = num2 / num1;break;default:throw new ArithmeticException("运算符有误");}numStack.push(res);}}System.out.println(res);}
}

逆波兰计算器

逆波兰表达式(后缀表达式)支持小括号和多位数整数计算,后缀表达式适合计算机进行运算,但是人却不太容易写出来,尤其是表达式很长的情况下,因此在开发中,我们需要将中缀表达式转成后缀表达式。

中缀表达式转后缀表达式规则

具体步骤如下:

  1. 初始化两个栈:存储中间结果的栈s1和运算符栈s2;定义-+优先级为1,*/优先级为2,其他0
  2. 从左至右扫描中缀表达式;
  3. 遇到操作数时,将其压s1;
  4. 遇到运算符时,比较其与s2栈顶运算符的优先级:
    1. 如果s2不为空 && 优先级<=栈顶运算符(优先级的定义判定了栈顶运算符为左括号“(”的情况,所以不用在考虑遇到做括号的情况),将s2栈顶的运算符弹出并压入到s1中,循环判断,再次转到(4-1)与s2中新的栈顶运算符相比较;
    2. 出了循环,将运算符压入s2;
  5. 遇到括号时:
    1. 如果是左括号“(”,则直接压入s2
    2. 如果是右括号“)”,则依次弹出s2栈顶的运算符,并压入s1,直到遇到左括号为止,此时将这一对括号丢弃
  6. 重复步骤3至5,直到表达式的最右边
  7. 将s2中剩余的运算符依次弹出并压入s1
  8. 依次弹出s1中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

举例分析

将中缀表达式 “1+((2+3)*4)-5” 转换为后缀表达式 "1 2 3 + 4 * + 5 –" 的过程如下:

扫描元素s1(栈底->栈顶)s2(栈底->栈顶)说明
1操作数,直接入栈s1
+1+s2为空,入栈s2
(1+ (左括号,直接入栈s2
(1+ ( ( 左括号,直接入栈s2
21 2+ ( ( 操作数,直接入栈s1
+1 2+ ( ( +s2栈顶运算符为左括号,入栈s2
31 2 3 + ( ( +操作数,直接入栈s1
)1 2 3 ++ ( 右括号,依次弹出s2栈顶的运算符,压入s1,直到遇到左括号为止,此时将这一对括号丢弃
*1 2 3 ++ ( *s2栈顶运算符为左括号,入栈s2
41 2 3 + 4+ ( *操作数,直接入栈s1
)1 2 3 + 4 *+右括号,依次弹出s2栈顶的运算符,压入s1,直到遇到左括号为止,此时将这一对括号丢弃
-1 2 3 + 4 * +--优先级不比+高,将+弹出并压入到s1中,此时s2为空,-入栈s2
51 2 3 + 4 * + 5-操作数,直接入栈s1
1 2 3 + 4 * + 5 -s2中剩余的运算符依次弹出并压入s1,结果为s1出栈的逆序

代码实现

import java.util.ArrayList;
import java.util.Stack;/*** @Author: * @Create: 2024-10-01 11:58* @Description: 1+((2+3)*4)-5 --> 1 2 3 + 4 * + 5 –*/
public class 中缀转后缀 {public static void main(String[] args) {String infix = "1+((2+3)*4)-5";ArrayList<String> suffixList = new ArrayList<>();Stack<String> oper = new Stack<>();int len = infix.length();for (int i = 0; i < len; i++) {char c = infix.charAt(i);if (Character.isDigit(c)) {int j = i;while (j < len && Character.isDigit(infix.charAt(j))) {j++;}suffixList.add(infix.substring(i, j));i = j - 1;} else if (c == '(') {oper.push(c + "");} else if (c == ')') {while (!oper.isEmpty() && !oper.peek().equals("(")) {suffixList.add(oper.pop());}oper.pop(); // 弹出左括号} else { // 运算符while (!oper.isEmpty() && getPriority(c + "") <= getPriority(oper.peek())) {suffixList.add(oper.pop());}oper.push(c + "");}}// 弹出剩下运算符while (!oper.isEmpty()) {suffixList.add(oper.pop());}System.out.println(suffixList);}private static int getPriority(String operator) {if ("*".equals(operator) || "/".equals(operator)) return 2;else if ("+".equals(operator) || "-".equals(operator)) return 1;else return 0;}
}

逆波兰计算器代码实现

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;/*** @Author: * @Create: 2024-10-01 13:51* @Description:*/
public class 逆波兰计算器 {public static void main(String[] args) {Scanner in = new Scanner(System.in);String infix = in.nextLine().replace(" ", "");// 转化后缀表达式List<String> suffix = changeToSuffix(infix);// 计算后缀表达式int res = calculateSuffix(suffix);System.out.println(res);}private static int calculateSuffix(List<String> suffix) {Stack<Integer> nums = new Stack<>();int res = 0;for (String s : suffix) {if (s.matches("\\d+")) {nums.push(Integer.parseInt(s));} else {Integer num1 = nums.pop();Integer num2 = nums.pop();switch (s) {case "*":res = num2 * num1;break;case "/":res = num2 / num1;break;case "+":res = num2 + num1;break;case "-":res = num2 - num1;break;default:throw new ArithmeticException("运算符有误");}nums.push(res);}}return res;}private static List<String> changeToSuffix(String infix) {Stack<String> oper = new Stack<>();ArrayList<String> res = new ArrayList<>();int len = infix.length();for (int i = 0; i < len; i++) {char c = infix.charAt(i);if (Character.isDigit(c)) {int j = i;while (j < len && Character.isDigit(infix.charAt(j))) {j++;}res.add(infix.substring(i, j));i = --j;} else if (c == '(') {oper.push(c + "");} else if (c == ')') {while (!oper.isEmpty() && !"(".equals(oper.peek())) {res.add(oper.pop());}oper.pop();} else {while (!oper.isEmpty() && getPriority(c + "") <= getPriority(oper.peek())) {res.add(oper.pop());}oper.push(c + "");}}while (!oper.isEmpty()) {res.add(oper.pop());}return res;}private static int getPriority(String operator) {if ("*".equals(operator) || "/".equals(operator)) return 2;else if ("+".equals(operator) || "-".equals(operator)) return 1;else return 0;}
}

相关文章:

后缀表达式中缀表达式转后缀表达式

后缀表达式的计算机求值 计算规则 从左至右扫描表达式&#xff0c;遇到数字时&#xff0c;将数字压入堆栈&#xff0c;遇到运算符时&#xff0c;弹出栈顶的两个数&#xff0c;用运算符对它们做相应的计算&#xff08;次顶元素 和 栈顶元素&#xff09;&#xff0c;并将结果入…...

Qemu开发ARM篇-7、uboot以及系统网络连接及配置

文章目录 1、uboot及linux版本网络设置1、宿主机虚拟网卡创建2、uboot使用tap0网卡3、启动测试 2、访问外网设置 在上一篇Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作并通过uboot进行挂载启动中&#xff0c;我们制作了AB分区系统镜像&#xff0c;并成功通过uboot加载kernel以及d…...

两数相加leetcode

第一个是测试用例代码&#xff0c;测试的是两个带头的逆序链表相加&#xff0c;并且有反转操作 但是题目要求的是不带头链表直接相加&#xff0c;不需要逆转&#xff0c;输出结果也是逆序的&#xff0c; 题解放在第二个代码中 #include<stdio.h> #include<stdlib.h…...

C0004.Qt中QComboBox设置下拉列表样式后,下拉列表样式无效的解决办法

问题描述 我们平时在使用Qt Creator对控件QComboBox的样式进行设置后&#xff0c;在运行程序启动界面时&#xff0c;发现设置的样式无效&#xff0c;效果如下&#xff1a; /* 设置下拉菜单框的样式 */ QComboBox QAbstractItemView {border: 1px solid rgb(161,161,161); /* …...

AI 对话工具汇总

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏AI_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 前言: 正文: 前言: 在科技飞速发展的时代&#xff0c;AI 对话正逐渐成为我们获取信息、交流思想的新方式。它以强…...

面试题05.08绘制直线问题详解(考察点为位运算符)

目录 一题目&#xff1a; 二详细思路汇总&#xff1a; 三代码解答&#xff08;带注释版&#xff09;&#xff1a; 一题目&#xff1a; leetcode原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二详细思路汇总&#xff1a; 这里先剧透一下简单版思路哦&…...

埃及 Explained

古埃及&#xff0c;位于尼罗河畔的神秘文明&#xff0c;曾在北非的荒漠中繁荣昌盛。这个充满谜团的王国凭借其宏伟的成就和神秘的文化&#xff0c;数百年来吸引了无数人的好奇心。 埃及人创造了复杂的象形文字&#xff0c;建造了像吉萨大金字塔这样宏伟的建筑&#xff0c;并通…...

【Linux】第一个小程序——进度条实现

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…...

如何确定光纤用几芯 用光纤与网线区别在哪里

光纤用几芯&#xff1f; 光纤芯数&#xff0c;主要和光纤连接的设备接口和设备的通信方式有关。一般来说&#xff0c;光纤中光芯的数量&#xff0c;为设备接口总数乘以2后&#xff0c;再加上10%&#xff5e;20&#xff05;的备用数量&#xff0c;而如果设备的通信方式有设备多…...

使用Chrome浏览器时打开网页如何禁用缓存

缓存是浏览器用于临时存储网页资源的一种机制&#xff0c;可以提高网页加载速度和减轻服务器负载。 然而&#xff0c;有时候我们需要阻止缓存中的Chrome浏览器&#xff0c;以便获取最新的网页内容。以下是一些方法可以实现这个目标&#xff1a; 1、强制刷新页面&#xff1a;在C…...

zabbix7.0创建自定义模板的案例详解(以监控httpd服务为例)

前言 服务端配置 链接: rocky9.2部署zabbix服务端的详细过程 环境 主机ip应用zabbix-server192.168.10.11zabbix本体zabbix-client192.168.10.12zabbix-agent zabbix-server(服务端已配置) 创建模板 模板组直接写一个新的&#xff0c;不用选择 通过名称查找模板&#xf…...

从零开始Ubuntu24.04上Docker构建自动化部署(五)Docker安装jenkins

安装jenkins 下载 sudo docker pull jenkins/jenkins:lts docker-compose启动 jenkins: image: jenkins/jenkins:lts container_name: compose_jenkins user: root restart: always ports: - 28080:8080 volumes: - /home/jenkins_home/:/var/jenkins_home - /usr/local/bin/d…...

【JS】访问器成员

前言 如下例&#xff0c;有一商品对象&#xff0c;其中属性分别为单价和数量以及一个用于计算总价的方法&#xff0c;需要通过 product.getTotal() 获得总价&#xff0c;也可以使用访问器成员getter控制属性读写逻辑&#xff0c;通过 product.total 的方式获取总价&#xff0c…...

五子棋双人对战项目(3)——匹配模块

目录 一、分析需求 二、约定前后端交互接口 匹配请求&#xff1a; 匹配响应&#xff1a; 三、实现游戏大厅页面&#xff08;前端代码&#xff09; game_hall.html&#xff1a; common.css&#xff1a; game_hall.css&#xff1a; 四、实现后端代码 WebSocketConfig …...

开源软件简介

一、开源运动的发起 近几十年&#xff0c;软件已经称为战略性的社会资源。各大软件供应商传统的对外封锁源代码的运营模式虽说有积极的一面&#xff0c;比如可以维护开发商的利益&#xff0c;使其可以持续地维护进一步开发的能力&#xff0c;以及可以保护软件商及客户的私密信息…...

Bruno:拥有 11.2k star 的免费开源 API 测试工具

Github 开源地址&#xff1a; https://github.com/usebruno/bruno 官网地址&#xff1a; https://www.usebruno.com/ 下载地址&#xff1a; https://www.usebruno.com/downloads 使用文档&#xff1a; https://docs.usebruno.com/ Bruno 是一款全新且创新的 API 客户端&…...

C动态内存管理

前言&#xff1a;不知不觉又过去了很长的一段时间。今天对C语言中的动态内存管理进行一个系统性的总结。 1 为什么要有动态内存分配 在C语言中&#xff0c;使用int&#xff0c;float&#xff0c;double&#xff0c;short等数据内置类型以及数组不是也可以开辟内存空间吗&…...

系列二、案例实操

一、创建表空间 1.1、概述 在Oracle数据库中&#xff0c;表空间是一个逻辑存储单位&#xff0c;它是Oracle数据库中存储数据的地方。 1.2、超级管理员登录 sqlplus / as sysdba 1.3、创建表空间 create tablespace water_boss datafile C:\Programs\oracle11g\oradata\orcl\…...

Python编码系列—Python状态模式:轻松管理对象状态的变化

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…...

卸载WSL(Ubuntu),卸载linux

禁用 WSL 功能 打开 Windows 功能&#xff1a; 按下 Windows R 打开运行对话框&#xff0c;输入 optionalfeatures&#xff0c;然后按回车。 禁用 WSL&#xff1a; 在弹出的 Windows 功能窗口中&#xff0c;找到 适用于 Linux 的 Windows 子系统&#xff08;Windows Subsystem…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...