逆波兰计算器的完整代码

前置知识:

 

 

将中缀表达式转为List方法:

 //将一个中缀表达式转成中缀表达式的List
    //即:(30+42)*5-6 ==》[(, 30, +, 42, ), *, 5, -, 6]
    public static List<String> toIndixExpressionList(String s) {
        //定义一个List,存放中缀表达式对应的内容
        List<String> ls = new ArrayList<String>();
        int i = 0; //这是一个指针,用于遍历 中缀表达式字符串
        String str = ""; //对多位数的拼接
        char c; //每遍历到一个字符,我需要加入到ls
        do {
            //如果是一个字符,直接添加到list
            if ((c = s.charAt(i)) < '0' || (c = s.charAt(i)) > '9') {
                ls.add("" + c);
                i++; //指针后移
            } else { //如果是一个数,需要考虑多位数
                str = ""; //将字符串置空
                while ((i < s.length()) && (c = s.charAt(i)) >= '0' && (c = s.charAt(i)) <= '9') {
                    str += c;
                    i++;
                }
                ls.add(str);
            }
        } while (i < s.length());
        return ls;
    }

将中缀表达式转化为后缀表达式(删除小括号):
 

 //将得到的中缀表达式对应的 List => 后缀表达式对应的 List
    // [(, 30, +, 42, ), *, 5, -, 6] ==》 30,42,+,5,*,6,-
    public static List<String> parseSuffixExpressionList(List<String> ls){
        //定义两个栈
        Stack<String> operStack = new Stack<String>();   //符号栈
        //因为 resStack ,这个栈整个转换过程中,没有pop操作,而且后面我们还需要逆序输出
        //因此我们这里使用 List<String> resList作为结果的存储
        List<String> resList = new ArrayList<String>();

        //遍历ls
        for (String item :ls) {
            //如果是一个数就直接加入到resList
            if(item.matches("\\d+")){
                resList.add(item);
            }else if (item.equals("(")){
                 operStack.push(item);
            }else if(item.equals(")")){
                //如果是右括号,则依次弹出 operStack 栈顶的运算符,并压入s2,
                // 直到遇到左括号为止,此时将这一对括号丢弃
                while (!operStack.peek().equals("(")) {
                    String temp = operStack.pop();
                    resList.add(temp);
                }
                    operStack.pop(); //将 ( 弹出符号栈,消除小括号
            }else {
                //当item的优先级 <= operStack 栈顶运算符,
                // 将 operStack 栈顶的运算符弹出并加入到 resList中
                // 再次与新 operStack 中新的栈运算符相比较
                while (operStack.size() != 0 && Operation.getValue(operStack.peek()) >= Operation.getValue(item)){
                    resList.add(operStack.pop());
                }
                //还需要将item压入栈中
                operStack.push(item);
            }
        }
        //将operStack中剩余的运算符依次弹出并加入到resList中
        while (operStack.size()!=0){
            resList.add(operStack.pop());
        }
        return resList; //注意因为是存放到List,因此按顺序输出就是对应的后缀表达式
    }

运算符的优先级:

//编写一个类 Operation 可以返回一个运算符 ,对应的优先级
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;

    //写一个方法,返回对应的优先级数字
    public static int getValue(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
            break;
            case "*":
                result = MUL;
            break;
            case "/":
                result = DIV;
            break;
            default:
                System.out.println("不存在该运算符~");
                break;
        }
        return result;
    }
}

 运算方法:

    public static int cal(List<String> list) {
        //创建一个栈
        Stack<String> stack = new Stack<String>();
        int res = 0;
        //遍历 list
        for (String s : list) {
            //这里使用正则表达式取出来数
            if (s.matches("\\d+")) {//如果是多个数字,直接入栈
                stack.push(s);
            } else {
                //如果取出的不是数字,需要弹出两个数字,进行运算,将运算结果,继续入栈操作
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                if (s.equals("+")) {
                    res = num1 + num2;
                } else if (s.equals("-")) {
                    res = num1 - num2;
                } else if (s.equals("*")) {
                    res = num1 * num2;
                } else if (s.equals("/")) {
                    res = num1 / num2;
                } else {
                    throw new RuntimeException("您输入的运算符有误!");
                }
                stack.push("" + res);
            }
        }
        return Integer.parseInt(stack.pop());
    }

测试类:

public static void main(String[] args) {
        //先定义逆波兰表达式
        //(3+4)*5-6 ==> 3 4 + 5 * 6 -
        //说明为了方便,逆波兰表达式的 数字和字符使用空格隔开
        String Expression = "(10+2)*5-6*2";

        /** 思路
         *  1. 先将 " 3 4 + 5 * 6 - " => 放到ArrayList中
         *  2. 将ArrayList 传递给一个方法,遍历ArrayList 配合栈 完成计算
         */

        //得到一个后缀表达式
        List<String> list = toIndixExpressionList(Expression);

        System.out.println("运算表达式为:" + list);

        //将中缀表达式转化为后缀表达式
        List<String> suffixExpression = parseSuffixExpressionList(list);
        System.out.println("后缀表达式为: "+suffixExpression);


        //现在进行运算
        System.out.println(list + " = " + cal(suffixExpression));
    }

 控制台输出:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YACS(上海计算机学会竞赛平台)一星级题集——水仙花指数

题目描述 定义一个正整数的十进制表示中各位数字的立方和为它的水仙花指数&#xff0c;给定一个整数 n&#xff0c;请计算它的水仙花指数。 例如 n1234 时&#xff0c;水仙花指数为 输入格式 单个整数&#xff1a;表示 n 输出格式 单个整数&#xff1a;表示 n 的水仙花指…

深⼊理解指针

1. 内存和地址 1.1 内存 在讲内存和地址之前&#xff0c;我们想有个⽣活中的案例&#xff1a; 假设有⼀栋宿舍楼&#xff0c;把你放在楼⾥&#xff0c;楼上有100个房间&#xff0c;但是房间没有编号&#xff0c;你的⼀个朋友来找你玩&#xff0c; 如果想找到你&#xff0c;就…

嵌入式中的基本定时器

学习目标 理解基本定时器的作用掌握定时器开发流程掌握基本定时器中断处理的操作流程掌握AHB和APB时钟查询方式理解周期,分频系数,周期计数,分频计数。掌握调试策略学习内容 基本定时器 只能用于定时计时操作,没有输出引脚通道的定时器,在GD32中, TIMER5和TIMER6为基本…

Ubuntu 常用命令之 reboot 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 reboot命令在Ubuntu系统中用于重新启动系统。这个命令通常需要管理员权限才能执行。 reboot命令的参数如下 -f 或 --force&#xff1a;强制重启&#xff0c;不调用shutdown -r进行友好重启。-p 或 --poweroff&#xff1a;在重启…

百度地图添加查询框

<div style"display:inline;float:left;margin: 10px"><el-input style"width: 400px" placeholder"输入地点" v-model"area" class"input-with-select"keyup.enter.native"searchMap"><el-button…

随机问卷调查数据的处理(uniapp)

需求&#xff1a;问卷调查 1.返回的数据中包含单选、多选、多项文本框、单文本框、图片上传 2.需要对必填的选项进行校验 3.非必填的多项文本框内容 如果不填写 不提交 表单数据格式 res{"code": 0,"msg": null,"data": [{"executeDay&…

lamda表达式(史上最全)

一、函数式接口 在jdk8中什么是函数式接口&#xff1a; 被FunctionalInterface注解修饰的。接口里边只有一个非default的方法。 满足以上2个条件的即为函数式接口&#xff0c;ps&#xff1a;即使一个接口没有FunctionalInterface修饰&#xff0c;但是满足2&#xff0c;那么这…

国产低成本Wi-Fi SoC解决方案芯片ESP8266与ESP8285对比差异

目录 ESP8266与ESP8285对比差异微信号&#xff1a;dnsj5343ESP8285简介ESP8285 主要特性Wi-Fi特性射频模块CPU特性硬件软件 ES8285 8266通用开发板 ESP8266与ESP8285对比差异 ESP8285相当于在ESP8266基础上多加了1/2MB Flash&#xff0c; ESP8285与ESP8266同用一套SDK&#xf…

异方差与多重共线性对回归问题的影响

异方差的检验 1.异方差的画图观察 2.异方差的假设检验&#xff0c;假设检验有两种&#xff0c;一般用怀特检验使用方法在ppt中&#xff0c;课程中也有实验&#xff0c;是一段代码。 异方差的解决办法 多重共线性 多重共线性可能带来的影响&#xff1a; 多重共线性的检验 多重…

德思特方案 | 德思特毫米波RIS研究测试方案:一站式助力工程师探索高频通信未来

来源&#xff1a;德思特测试测量 德思特方案 | 德思特毫米波RIS研究测试方案&#xff1a;一站式助力工程师探索高频通信未来 原文链接&#xff1a;德思特方案 | 德思特毫米波RIS研究测试方案&#xff1a;一站式助力工程师探索高频通信未来 欢迎关注虹科&#xff0c;为您提供最…

KubeSphere应用【五】发布镜像至Harbor

一、IDEA发布镜像至Docker 1.1IDEA安装Docker插件 1.2配置Docker服务器地址 1.3编写POM.XML文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/20…

Java学习常用实用类2

1 StringTokenizer类 字符串分析器&#xff0c;能够从一个字符串中根据指定的分隔符拆分出若干单词 StringTokenizer(String s) 使用默认分隔符集合&#xff0c;即&#xff1a;空格符、换行符、回车符、Tab符、进纸符 StringTokenizer(String s, String delim) 指定分…

cilium原理之ebpf尾调用与trace

背景 在深入剖析cilium原理之前&#xff0c;有两个关于epbf的基础内容需要先详细介绍一下&#xff1a; 1. ebpf尾调用 尾调用类似于程序之间的相互跳转&#xff0c;但它的功能更加强大。 2. trace 虽然之前使用trace_printk输出日志&#xff0c;但这个函数不能多用&#x…

数据仓库-数据治理小厂实践

一、简介 数据治理贯穿数仓中数据的整个生命周期&#xff0c;从数据的产生、加载、清洗、计算&#xff0c;再到数据展示、应用&#xff0c;每个阶段都需要对数据进行治理&#xff0c;像有些比较大的企业都是有自己的数据治理平台或者会开发一些便捷的平台&#xff0c;对于没有平…

从DevOps状态报告看技术团队的文化建设

本文源自一次内部分享&#xff0c;借由此机会又把历年的DevOps状态报告翻看了一遍&#xff0c;其实大多数时候我们对于DevOps的理解都在于流程&#xff0c;工具&#xff0c;实践这些看得见摸得着的东西&#xff0c;但就像文末的几点思考所说的那样&#xff0c;我们一直相信技术…

轴承故障诊断分类模型全家桶-最全教程

Python轴承故障诊断 (一)短时傅里叶变换STFT-CSDN博客 Python轴承故障诊断 (二)连续小波变换CWT-CSDN博客 Python轴承故障诊断 (三)经验模态分解EMD-CSDN博客 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Trans…

VM Group

在复杂方案中模块过多可能造成查看或修改方案时存在视觉混乱&#xff0c;不够直观。此时可利用Group模块进行模块整合&#xff0c;同时Group模式也兼容循环的功能&#xff0c;如下图所示。 双击Group模块可进入Group内部&#xff0c;如下图所示。 在Group模块单击 可设置输入、…

Spring Cloud+SpringBoot b2b2c:Java商城实现一件代发设置及多商家直播带货商城 免 费 搭 建

【saas云平台】打造全行业全渠道全场景的saas产品&#xff0c;为经营场景提供一体化解决方案&#xff1b;门店经营区域化、网店经营一体化&#xff0c;本地化、全方位、一站式服务&#xff0c;为多门店提供统一运营解决方案&#xff1b;提供丰富多样的营销玩法覆盖所有经营场景…

北斗卫星时钟同步服务器对电力系统有多重要?

随着计算机和网络通信技术的飞速发展&#xff0c;火电厂热工自动化系统数字化、网络化的时代已经到来。一方面它为控制和信息系统之间的数据交换、分析和应用提供了更好的平台&#xff0c;另一方面对各种实时和历史数据时间标签的准确性提出了更高的要求。 通过卫星时钟来统一全…

Tomcat报404问题解决方案大全(包括tomcat可以正常运行但是报404)

文章目录 Tomcat报404问题解决方案大全(包括tomcat可以正常运行但是报404)1、正确的运行页面2、报错404问题分类解决2.1、Tomcat未配置环境变量2.2、IIs访问权限问题2.3、端口占用问题2.4、文件缺少问题解决办法&#xff1a; Tomcat报404问题解决方案大全(包括tomcat可以正常运…