(四)栈—中缀表达式转后缀表达式

news2024/12/23 22:18:47

 一、基本介绍

二、应用实例


        将中缀表达式"1+((2+3)x4)-5" 转换为 后缀表达式"1 2 3 + 4 x + 5 -"
        思路:
            1.初始化两个栈:运算符栈s1和存储中间结果的栈s2;
            2.从左至右扫描中缀表达式;
            3.扫描到操作数直接压入栈s2中;
            4.扫描到运算符时,比较其与s1栈顶运算符的优先级:
                    4.1若s1为空或者栈顶运算符为左括号,则直接将扫描到的运算符压入s1;
                    4.2否则,若扫描到的运算符优先级比s1栈顶运算符高,也将其压入栈s1;
                    4.3否则,将s1栈顶运算符弹出并压入到栈s2中,同时再次与s1中新的栈顶运算符比较;
            5.扫描到括号时:
                    5.1若扫描到的是左括号,则直接压入到栈s1中;
                    5.2若扫描到的是右括号,则依次弹出s1栈顶运算符,并压入栈s2,直至遇到左括号为止,最后将栈s1中的左括号丢弃;
            6.重复步骤2-5,直到扫描到中缀表达式的最右边;
            7.将s1中剩余的运算符依次弹出并压入栈s2;
            8.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式。
 

package stack;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class InffixToSuffixExpression {
    public static void main(String[] args) {
        String inffixExpression = "1+((2+3)*4)-5";
        List<String> inffiExpression_list = toList(inffixExpression); // 获得中缀表达式对应的List集合
        List<String> suffixExpression_list = toParseSuffixExpression(inffiExpression_list);
        Collections.reverse(suffixExpression_list); // 将list集合逆序,即为对应的后缀表达式
        String suffixExpression = String.join("", suffixExpression_list); // 将list集合转为字符串
        System.out.println("中缀表达式:" + inffixExpression);
        System.out.println("后缀表达式:" + suffixExpression);
        System.out.println("后缀表达式(逆波兰表达式)求值:" + calculate(suffixExpression_list));
    }

    //  inffixExpression = "1+((2+3)*4)-5";
    public static List<String> toList(String inffixExpression) {
        List<String> list = new ArrayList<>();
        char ch = ' ';
        int index = 0;
        String temp;
        while (index != inffixExpression.length()) {
            //  如果该字符是非数字,则将其直接放入list数组
            if ((ch = inffixExpression.charAt(index)) < 48 || (ch = inffixExpression.charAt(index)) > 57) {
                list.add(ch + "");
                index++;
            } else {
                //  如果该字符是数字,则需要考虑多位数的情况
                temp = "";  // 每循环一轮,都需将字符串置为空
                while (index < inffixExpression.length() && (((ch = inffixExpression.charAt(index)) >= 48) && ((ch = inffixExpression.charAt(index)) <= 57))) {
                    temp += ch;
                    index++;
                }
                list.add(temp);
            }
        }
        return list;
    }

    private static List<String> toParseSuffixExpression(List<String> list) {
        Stack operStack = new Stack(32);
        Stack tempStack = new Stack(32);
        String op = "";
        //  2、从左至右扫描中缀表达式
        for (String item : list) {
            //  3、遇到是数字时
            if (item.matches("\\d+")) {  // 匹配多位数
                tempStack.push(item);
                //  3.1、遇到左括号
            } else if (item.equals("(")) {
                operStack.push(item);
                //  3.2、遇到右括号
            } else if (item.equals(")")) {
                while (!operStack.peek().equals("(")) {
                    tempStack.push(operStack.pop());
                }
                operStack.pop(); // 将左括号出栈
                //  4、遇到运算符时
            } else {
                // 4.1、operStack栈为空 或 栈顶元素为( 时,直接将元素入栈
                if (operStack.isEmpty() || operStack.peek().equals("(")) {
                    operStack.push(item);
                    // 4.2、该字符元素优先级比栈顶元素优先级高,则直接入栈
                } else if (operStack.priority(item) > operStack.priority(operStack.peek())) {
                    operStack.push(item);
                } else {
                    //  4.3、该字符元素的优先级 <= 栈顶元素的优先级
                    while(!operStack.isEmpty() && operStack.priority(item) <= operStack.priority(operStack.peek())) {
                        tempStack.push(operStack.pop());
                    }
                    //  退出while循环时,一般为当前元素的优先级高于栈顶元素的优先级,所以要将该元素直接入栈
                    operStack.push(item);
                }
            }
        }

        //  5、将operStack剩余的运算符弹出并压入tempStack
        while (!operStack.isEmpty()) {
            tempStack.push(operStack.pop());
        }

        //  6、弹出tempStack的元素放入List数组中返回,结果的逆序即为对应的后缀表达式
        List<String> resultList = new ArrayList();
        while(!tempStack.isEmpty()) {
            resultList.add(tempStack.pop());
        }
        return resultList;
    }

    private static String calculate(List<String> list) {
        Stack stack = new Stack(16);
        int num1 = 0;
        int num2 = 0;
        int res = 0;
        for (String item : list) {
            if (item.matches("\\d+")) { // 匹配多位数字
                stack.push(item);
            } else {
                num1 = Integer.parseInt(stack.pop());
                num2 = Integer.parseInt(stack.pop());
                if (item.equals("+")) {
                    res = num1 + num2;
                } else if (item.equals("-")) {
                    res = num2 - num1;
                } else if (item.equals("*")) {
                    res = num1 * num2;
                } else if (item.equals("/")) {
                    res = num2 / num1;
                } else {
                    System.out.println("无效运算符!");
                }
                stack.push(res+"");
            }
        }
        //  栈中最后的值即为表达式的结果
        return stack.pop();
    }

}

class Stack {
    private String[] arr;
    private int maxSize;
    private int top;
    public Stack(int maxSize) {
        this.maxSize = maxSize;
        this.arr = new String[maxSize];
        this.top = -1;
    }

    public String peek() {
        return arr[top];
    }

    public void push(String val) {
        if (isFull()) {
            throw new RuntimeException("栈满,入栈失败!");
        }
        arr[++top] = val;
    }

    public String pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空,出栈失败!");
        }
        return arr[top--];
    }

    public void print() {
        if (isEmpty()) {
            throw new RuntimeException("栈空,出栈失败!");
        }
        System.out.print("栈元素:");
        for (int i = top; i >= 0 ; i--) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public boolean isEmpty() {
        if (top == -1) {
            return true;
        }
        return false;
    }

    public boolean isFull() {
        if (top == maxSize - 1) {
            return true;
        }
        return false;
    }

    public int priority(String ch) {
        if (ch == "x" || ch == "/") {
            return 1;
        } else if (ch == "+" || ch == "-") {
            return 0;
        } else {
            return -1;
        }
    }
}

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

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

相关文章

【c++初阶】第九篇:vector(常用接口的使用 + 模拟实现)

文章目录vector介绍vector的使用vector的定义vector iterator(迭代器) 的使用begin和endrbegin和rendvector 空间增长问题size和capacityreserve和resize&#xff08;重点&#xff09;测试vector的默认扩容机制emptyvector的增删查改push_back和pop_backinsert和erasefindswapo…

GPT-4创造者:第二次改变AI浪潮的方向

OneFlow编译 翻译&#xff5c;贾川、杨婷、徐佳渝 编辑&#xff5c;王金许 一朝成名天下知。ChatGPT/GPT-4相关的新闻接二连三刷屏朋友圈&#xff0c;如今&#xff0c;这些模型背后的公司OpenAI的知名度不亚于任何科技巨头。 不过&#xff0c;就在ChatGPT问世前&#xff0c;Ope…

Verilog Tutorial(10)如何实现可复用的设计?

写在前面在自己准备写verilog教程之前&#xff0c;参考了许多资料----FPGA Tutorial网站的这套verilog教程即是其一。这套教程写得不错&#xff0c;只是没有中文&#xff0c;在下只好斗胆翻译过来&#xff08;加了自己的理解&#xff09;分享给大家。这是网站原文&#xff1a;h…

【敬伟ps教程】平移、缩放、移动、选区

文章目录平移抓手工具旋转抓手缩放工具移动工具详解选区选区工具详解平移 抓手工具 当打开一张大图时&#xff0c;可以通过修改底部的百分比或使用抓手工具&#xff08;H或在任何时候按住空格键来使用抓手工具&#xff09;来查看更多细节 使用抓手工具时滚动所有打开的文档&…

几何的显式表示 - 曲线和曲面

点云&#xff1a;list of points&#xff08;x, y, z&#xff09; 将点云变成多边形的面&#xff0c;从而在计算机中输出多边形网格&#xff1a;Polygon Mesh 就是 拆成小三角 贝塞尔曲线 定义曲线只要满足起止点即可&#xff0c;P1&#xff0c;P2决定了它要往哪个方向弯 de Ca…

STM32 HAL库PID控制电机 第三章 PID控制双电机

STM32 HAL库PID控制电机 第三章 PID控制双电机 注:本文含全部PID控制代码,保证可以运行,如不能运行可以留言回复 1 基础配置 1.1 编码器电路图及配置 引脚定时器通道PA0TIM2_CH1PA1TIM2_CH2PB6TIM4_CH1PB7TIM4_CH2因此需要把TIM2、TIM4配置为编码器模式。在STM32CubeMX中…

如何在react中处理报错

本文为 360 奇舞团前端工程师翻译 原文地址&#xff1a;https://www.developerway.com/posts/how-to-handle-errors-in-react我们都希望我们的应用能稳定、完美运行&#xff0c;并且能够考虑到每一个边缘情况。但是现实情况是&#xff0c;我们是人&#xff0c;是人就会犯错&…

【区块链】走进web3的世界-DApp如何快速接入wall

在web3中&#xff0c;wall是您进入区块链的一个标识&#xff0c;每个用户使用的wall都不近相同&#xff0c;因此接入更多的wall是很有必要的&#xff0c;从用户角度来说&#xff0c;非必要情况下&#xff0c;我是不愿意去额外下载wall的。因此今天我们来聊一下&#xff0c;DApp…

手把手教你搭建 Docker API 未授权漏洞环境

环境&#xff1a;ubuntu 16.04 我是在虚拟机中安装了ubuntu 16.04的环境&#xff0c;里面暂时没有docker、ssh远程、vim等。 1. 更换国内源 直接输入docker 这里没有安装&#xff0c;那安装下 sudo apt install docker.io 开始安装 因为我没有修改源&#xff0c;所以这个速…

数据的表示和存储1

目录 数制和编码 信息的二进制编码 数值数据的表示 进制计数制 定点数和浮点数 定点数的编码表示 原码表示 补码表示 求特殊数的补码 求真值的补码 求补码的真值 移码表示Excess (biased) notiion C语言中的整数 无符号整数(unsigned integer) 带符号整数&#xff0…

QT sql查询模型,视图显示

SQL模型定义定义sql查询模型查询设置格式创建视图并显示setHeaderData() 函数定义 SQL 查询模型&#xff08;QSqlQueryModel&#xff09;是 Qt 提供的一种数据模型&#xff0c;用于执行 SQL 查询并返回结果集。它继承自 QSqlTableModel 类&#xff0c;可以使用 QSqlQuery 对象执…

【eXtplorer】本地搭建免费在线文件管理器并实现在外远程登录

文章目录1. 前言2. eXtplorer网站搭建2.1 eXtplorer下载和安装2.2 eXtplorer网页测试2.3 cpolar的安装和注册3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置4.公网访问测试5.结语1. 前言 通过互联网传输文件&#xff0c;是互联网最重要的应用之一&#xff0c;无论是网上…

springboot学习2

一、spring boot自动装配原理 pom.xml spring-boot-dependencies 核心依赖在父工程中 在写或者引入一些spring boot依赖的时候&#xff0c;不需要指定版本&#xff0c;因为有这些版本仓库启动器 <dependency><groupId>org.springframework.boot</groupId>&…

使用golang实现日志收集系统的logagent

整体架构 参考 七米老师的日志收集项目 主要用go实现logagent的部分&#xff0c;logagent的作用主要是实时监控日志追加的变化&#xff0c;并将变化发送到kafka中。 之前我们已经实现了 用go连接kafka并向其中发送数据&#xff0c;也实现了使用tail库监控日志追加操作。 我们…

【Java基础】反射详述简单模拟SpringMVC

&#x1f6a9; 本文已收录至专栏&#xff1a;JAVA基础 &#x1f44d;希望能对你有所帮助 一.概述 反射是指对于任何一个Class类&#xff0c;在运行的时候都可以直接得到这个类全部成分&#xff0c;使得我们可以动态操作Java代码&#xff0c;同时反射也破坏了Java的封装性。 例…

如何清理电脑缓存,分享4个简单方法!

案例&#xff1a;如何清理电脑缓存 【朋友们&#xff01;我感觉我电脑的内存已经严重不足了&#xff0c;想清理下电脑的缓存释放空间&#xff0c;却不知如何清理&#xff0c;大家有什么好的方法吗&#xff1f;】 经常使用电脑的朋友可能都会发现&#xff0c;好像我们没下载什…

平台和编译器决定 char 是 signed char 或者 unsigned char

平台和编译器决定 char 是 signed char 或者 unsigned charThe C and C standards allows the character type char to be signed or unsigned, depending on the platform and compiler. Most systems, including x86 GNU/Linux and Microsoft Windows, use signed char, but …

NetCore3.1或Net6.0项目升级到Net7.0

其实与我之前发布的步骤基本一致&#xff0c;升级到net6.0之后&#xff0c;在升级net7.0基本没有可修改的代码&#xff0c;只是升级一些nuget包而已&#xff0c;NetCore3.1升级到Net6.0&#xff0c;可参考此文章&#xff1a;NetCore3.1项目升级到Net6.0_csdn_aspnet的博客-CSDN…

Rust China Conf 2023 筹备启动:议题征集开始

大会介绍Rust China Conf 2023 由 Rust 中文社区发起主办、知名企业和开源组织联合协办&#xff0c;是年度国内规模最大并唯一的 Rust 线下大型会议&#xff0c;深受 Rust 中文社区开发者与相关企业的喜爱与推崇。本次大会为线下会议&#xff0c;将于6月17日-18日在上海举办&am…

Java虚拟机总结

前言 Java是目前用户最多、使用范围最广的软件开发技术之一。Java的技术体系主要由支撑Java程序运行的虚拟机、提供各开发领域接口支持的Java APl、,Java编程语言及许多第三方Java框架&#xff08;如Spring、Struts等&#xff09;构成。在国内&#xff0c;有关Java APl、Java语…