模拟栈解决表达式求值-java

news2024/12/24 8:51:55

主要讲述了通过栈来解决后缀表达式,来计算出表达式的结果,可以好好熟悉一下思路。

目录

前言

一、表达式求值问题

二、栈模拟计算表达式

1.算法思路

2.代码解释

三、代码实现

1.代码如下:

2.测试样例如下:

 3.运行结果如下:

总结


前言

主要讲述了通过栈来解决后缀表达式,来计算出表达式的结果,可以好好熟悉一下思路。


一、表达式求值问题

给定一个表达式,其中运算符仅包含 +,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。

注意:

  • 数据保证给定的表达式合法。
  • 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现。
  • 题目保证表达式中所有数字均为正整数。
  • 题目保证表达式在中间计算过程以及结果中,均不超过 2^31 - 1。
  • 题目中的整除是指向 0取整,也就是说对于大于 0 的结果向下取整,例如 5/3=1,对于小于 0 的结果向上取整,例如 5/(1−4)=−1。
  • C++和Java中的整除默认是向零取整;Python中的整除//默认向下取整,因此Python的eval()函数中的整除也是向下取整,在本题中不能直接使用。

输入格式

共一行,为给定表达式。

输出格式

共一行,为表达式的结果。

数据范围

表达式的长度不超过 100000。

二、栈模拟计算表达式

1.算法思路

图1.1示例 

 当我们要计算一个表达式的结果的时候,我们平常所看到的式子其实就是中缀表达式,即图1.1中树的中序遍历(左根右)的结果,当然其中缺少了小括号。然而计算机识别的时候后缀表达式往往更容易计算,即树的后序遍历(左右根)。

那么我们如何让计算机来实现对后缀表达式进行计算呢?

模拟栈计算中缀表达式的步骤可以分为几个关键阶段,主要是通过栈来处理运算符和操作数,以正确求解表达式的值。

1.操作数栈和运算符栈的准备

  • 准备两个栈:一个用于存放操作数(数字)的栈 ,一个用于存放运算符和括号的栈 。

2.遍历表达式

  • 从左到右逐个读取表达式中的字符或子串。

3.处理操作数

  • 遇到操作数(通常是连续的数字),将其压入操作数栈。

4.处理运算符

遇到运算符或括号时,根据其优先级和结合性进行处理:

  • 左括号 (:直接将其压入运算符栈。
  • 右括号 ):从运算符栈中弹出运算符,并依次执行相应的计算,直到遇到匹配的左括号为止。
  • 其他运算符:比较当前运算符与栈顶运算符的优先级:
  1. 如果当前运算符优先级高于栈顶运算符,将当前运算符压入运算符栈 。
  2. 否则,从运算符栈中弹出栈顶运算符,并执行相应的计算操作,直到当前运算符可以入栈为止。

根据上图这个式子,我们可以很明白的看出,当我们此时的操作符 *,那么我们符号栈中对应的操作符就是+,*号的优先级大于+,那么我们正常的顺序是先算乘除后算加减,那么就验证了,当我们当前运算符的优先级大于符号栈顶优先级的时候是不进行运算的,此时将对应的操作数和符号分别压入符号栈和操作数栈中即可。

(且符号栈中符号的运算级一定是递增的)

如果我们此时当前的运算符是/,此时栈顶操作符是*,乘除是属于同一个优先级的,所以我们此时就可以将操作数栈中弹出两个数进行运算,将运算后的结果加入操作数栈,此时再将*弹出,此时的运算符是*,栈顶是+,那么我们也是先算乘法再算加法。此时就说明了,当前运算符的优先级大于等于栈顶运算符的优先级时,就可以进行运算符栈弹出一个元素,

 

2.代码解释

 首先创建两个栈,一个是操作数栈num,一个是运算符号栈op;用一个map集合用来表示运算符的优先级

接下来我们读入表达式str。遍历每一个字符,当字符是数字的时候,我们还需要判断它的下一位还是不是数字,如果还是数组说明是一个整数,那么就将数组压入操作数栈。如果不是数字,就说明此时是运算符。如果此时是操作符,我们就要判断此时操作符是否是括号,左括号直接压入运算符号栈;如果是右括号,那么我们当运算符栈弹出的运算符不是左括号的时候,依次进行弹出一个运算符,两个操作数,进行相应运算,并将运算结果压入操作数栈。(此时运算符栈中优先级一定是递增的)。当此时符号栈中是空的,我们直接把当前运算符直接压入运算符号栈即可;当此时运算符不是上述任意一种情况时,当运算符号栈不为空,且当前符号栈不是左括号且当前运算符的优先级大于运算符号栈的栈顶元素的优先级时,我们还是进行依次进行弹出一个运算符,两个操作数,进行相应运算,并将运算结果压入操作数栈。此时再将当前运算符压入运算符栈顶即可。

当我们整个表达式遍历结束时,如果运算符号栈仍有元素的时候,就说明还没运算结束,且运算符号栈优先级一定是递增的,我们依次进行弹出一个运算符,两个操作数,进行相应运算,并将运算结果压入操作数栈。最后操作数栈最后剩下的一个元素就行表达式的最后结果。

三、代码实现

1.代码如下:


import java.io.*;
import java.util.*;

public class 表达式求值 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);

    static Stack<Integer> num = new Stack<>();
    static Stack<Character> op = new Stack<>();
    public static void main(String[] args)throws Exception {
        Map<Character, Integer> map = new HashMap<>();
        map.put('+', 1);
        map.put('-', 1);
        map.put('*', 2);
        map.put('/', 2);
        String str = nextLine();
        int len = str.length();
        for(int i=0; i<len; i++) {
            char ch = str.charAt(i);
            if(Character.isDigit(ch)) {
                int x = 0, j = i;
                while (j < len && Character.isDigit(str.charAt(j))) {
                    x = x * 10 + str.charAt(j) - '0';
                    j++;
                }
                num.push(x);
                i = j - 1;
            }else if(str.charAt(i)=='(') {
                op.push(str.charAt(i));
            }else if(str.charAt(i)==')') {
                while(op.peek() != '(') {
                    eval();
                }
                op.pop();
            } else if (op.isEmpty()) {
                op.push(str.charAt(i));
            } else {
                while(!op.isEmpty() && op.peek() != '(' && map.get(op.peek()) >= map.get(str.charAt(i))) {
                    eval();
                }
                op.push(str.charAt(i));
            }
        }
        while(op.size() > 0) {
            eval();
        }
        pw.println(num.peek());
        pw.flush();
    }
    public static void eval(){
        int num1 = num.pop();
        int num2 = num.pop();
        char x = op.pop();
        if(x =='+'){
            num.push(num2 + num1);
        }else if(x =='-'){
            num.push(num2 - num1);
        }else if(x =='*'){
            num.push(num2 * num1);
        }else if(x =='/'){
            num.push(num2 / num1);
        }
    }
    public static int nextInt()throws Exception{
        st.nextToken();
        return (int)st.nval;
    }
    public static String nextLine()throws Exception{
        return br.readLine();
    }
}

2.测试样例如下:

(2+2)*(1+1)

 3.运行结果如下:

8

 4 * 2 = 8


总结

上述主要讲述了通过栈来解决后缀表达式,来计算出表达式的结果,可以好好熟悉一下思路。

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

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

相关文章

【轨物推荐】经济长波:创新周期的历史

原创 丑丑姐姐 专利分析可视化 2021年08月01日 21:18 图片来源&#xff1a;Visual Capitalist 在开始本文之前&#xff0c;我们先来学习两个概念&#xff1a; 经济长波&#xff08;Long Waves&#xff09;&#xff0c;亦称“大循环理论”、“康德拉季耶夫周期”。经济长波理论…

redis持久化存储,rdb快照文件,aof文件

redis作为内存数据库&#xff0c;在内存中进行读写操作&#xff0c;将读写操作从毫秒级别降为纳秒级别&#xff0c;得到极大的性能提升&#xff0c;与此同时&#xff0c;作为内存数据库其也有致命缺陷&#xff0c;一旦redis发生意外宕机&#xff0c;那么内存中的数据将全部消失…

智慧医院临床检验管理系统源码(LIS),全套LIS系统源码交付,商业源码,自主版权,支持二次开发

实验室信息系统是集申请、采样、核收、计费、检验、审核、发布、质控、查询、耗材控制等检验科工作为一体的网络管理系统。它的开发和应用将加快检验科管理的统一化、网络化、标准化的进程。一体化设计&#xff0c;与其他系统无缝连接&#xff0c;全程化条码管理。支持危机值管…

如何手动修复DLL丢失?2种手动修复dll文件方法

DLL&#xff08;动态链接库&#xff09;文件是Windows操作系统中非常重要的组成部分&#xff0c;它们包含了程序运行所需的代码和数据。然而&#xff0c;由于各种原因&#xff0c;如系统更新、软件卸载不当或病毒感染&#xff0c;DLL文件有时会丢失或损坏&#xff0c;导致程序无…

Python pyautogui 自动控制 MDK Keil_v5 Pack Installer 的 Packs 安装过程

MDK Keil_v5 安装完成后&#xff0c;会自动进行 Pack Installer 的 Packs 安装&#xff0c;安装过程中首先 install 需要一行行用鼠标点&#xff0c;然后每一行的 Pack 都会出现同意安装或连接超时的弹窗&#xff0c;需要鼠标操作确认。 pyautogui 可以帮助自动控制鼠标完成确…

【C++】关于仿函数Functor 的理解和应用

C中的仿函数&#xff08;Functor&#xff09;&#xff1a;深入理解与应用 仿函数的基本概念仿函数在STL中的应用仿函数的分类STL中的常见仿函数 仿函数的优势结论 在C编程中&#xff0c;仿函数&#xff08;Functor&#xff09;是一种特殊的类&#xff0c;它通过重载函数调用运算…

【RabbitMQ】通配符模式(Topics)

一、基本概念 生产者&#xff08;Producer&#xff09;&#xff1a;发送消息到RabbitMQ交换机的程序。生产者定义消息的路由键&#xff0c;用于标识消息的目的地。交换机&#xff08;Exchange&#xff09;&#xff1a;接收生产者发送的消息&#xff0c;并根据路由键和绑定规则…

IT运维中,如何快速进行故障排查?(以银行APP交易故障为例)

一、事件背景 正值"五一"黄金周旅游高峰期&#xff0c;某城商行的手机APP突然出现大面积交易失败和严重卡顿现象。据初步统计&#xff0c;从上午10点开始APP的交易成功率从正常的99%骤降至75%左右&#xff0c;用户反馈的交易失败投诉量在短短2小时内激增了500%。与此…

volatile 关键字的两层语义

volatile 关键字的两层语义 1、可见性2、禁止指令重排序3、工作机制4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; volatile 关键字在Java并发编程中扮演着重要角色&#xff0c;它主要用于保证变量的可见性和禁止指令重排序。 1、…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-63 - Canvas和SVG元素定位

软件测试微信群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 今天宏哥分享的在实际测试工作中很少遇到&#xff0c;比较生僻&#xff0c;如果突然遇到我们可能会脑大、懵逼&#xff0c;一时之间不知道怎么办&#xff1f;所以宏哥这里提供…

redis高持久化、RDB、AOF

redis高可用 redis当中&#xff0c;高可用概念会更宽泛一些。 除了正常服务以外&#xff0c;数据量的扩容&#xff0c;数据安全。 实现高可用的方式&#xff1a; 1、持久化 最简单的高可用方法 主要功能&#xff1a;备份数据 把内存的数据保存到硬盘当中。 2、主从复制 3、…

【CAN通讯系列8】如何准确接收数据?

在 【CAN通讯系列7】波特率是什么&#xff1f;已经介绍了CAN位时间和采样点等概念&#xff0c;每1位由同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)和相位缓冲段2(PBS2)四个段组成&#xff0c;这个也成为位时序&#xff0c;采样点位置处于PBS1和PBS2的交界处&#xff0c;如…

开源跨平台SQL编辑器:Beekeeper Studio

Beekeeper Studio&#xff1a; 简化SQL体验&#xff0c;提升数据库效率。- 精选真开源&#xff0c;释放新价值。 概览 Beekeeper Studio&#xff0c;一款为现代数据库管理而生的跨平台SQL客户端&#xff0c;以其简洁直观的界面和强大的功能&#xff0c;赢得了开发者和数据库管…

betterzip免费版 betterzip破解版 betterzip注册码密钥 betterzip解压缩软件下载安装教程

基于Mac开发的解压缩软件就那么几款&#xff0c;BetterZip解压缩软件估计是Mac上非常受欢迎的压缩工具。苹果Mac电脑上虽然有自带的归档实用工具&#xff0c;但是功能过于单一&#xff0c;对很多格式的压缩文件无能为力&#xff0c;特别像使用Windows电脑的朋友压缩文件习惯使用…

搜索型和XX型注入

"Pikachu"通常是指一个安全漏洞学习平台&#xff0c;它模拟了各种Web应用中的安全漏洞&#xff0c;以便于学习者实践和了解这些漏洞的工作原理。在这个平台上&#xff0c;你可以找到不同类型的SQL注入漏洞来练习和学习如何利用与防御它们。 搜索型注入&#xff08;也…

同步交互与异步交互:深入解析与选择

同步交互与异步交互&#xff1a;深入解析与选择 1、同步交互2、异步交互3、选择策略 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在软件开发的世界里&#xff0c;交互方式主要分为两大类&#xff1a;同步与异步。下面是对这两种方式的解…

AGI思考探究过程中的意义、价值与乐趣Ⅲ

「融合RL与LLM思想&#xff0c;探寻世界模型以迈向AGI」这篇文章也探究了思维系统的两种推理模式&#xff1a;系统Ⅰ&#xff08;快思考&#xff09;和系统Ⅱ&#xff08;慢思考&#xff09;在推理过程的本质普遍性及表象差异性&#xff0c;以及尝试挖掘快慢思考是否与两类学习…

用于自动驾驶的基于立体视觉的语义 3D 对象和自我运动跟踪

Stereo Vision-based Semantic 3D Object and Ego-motion Tracking for Autonomous Driving 论文 摘要&#xff1a; 我们提出了一种基于立体视觉的方法&#xff0c;用于在动态自动驾驶场景中跟踪相机自我运动和 3D 语义对象。我们建议使用易于标记的 2D 检测和离散视点分类以及…

【SQL Server】网络通信基础

目录 网络通信基础 网络协议概述 TCP/IP 协议栈 端口和地址绑定 网络通信基础 网络协议概述 网络协议是一组规则和标准&#xff0c;定义了数据在网络中的传输方式。这些协议确保不同设备之间的通信顺畅且高效。网络协议分为多个层次&#xff0c;每个层次负责特定的任务。…

直播狂欢下的隐忧|专题报告集

原文链接&#xff1a;https://tecdat.cn/?p37200 从草根逆袭的烤摊主郭有才&#xff0c;仅用9天便突破千万粉丝&#xff0c;日入惊人的380万&#xff0c;到菏泽因直播热潮连夜紧急修路&#xff0c;这一切看似光鲜的背后&#xff0c;实则暗流涌动。 模仿“反诈老陈”、“保安…