【数据结构与算法 7】中缀表达式转为后缀表达式,实现逆波兰计算器

基本计算器的初步实现——将表达式转换成逆波兰表达式并计算结果 作为栈的初学者,表达式求值的问题给我带来了非常多的思考。目前,我还只能实现非负整数的 带加减乘除模及括号运算的表达式求值,且效率也算高。但还是想记录一下这个问题实现的整个过程。 我们平常习惯的表达式称为中缀表达式,是语法树中序遍历的结果,这样用计算机来计算并不容易,特别是遇到括号中还有很多括号的情况。也就是说,我们面对的最大的问题是,当不知道有多少个优先级需要判断时,我们到底该怎么办呢?前人真的... 阅读详情

一、中缀表达式

中缀表达式是一个通用的算术或逻辑公式表示方法。我们小学学的加减乘除就是所谓的中缀表达式,便于人类计算的表达式。

例如:(3+4)* 5 - 6

二、前缀表达式和后缀表达式

(3+4)* 5 - 6的前缀表达式是- * + 3 4 5 6 

(3+4)* 5 - 6的后缀表达式是 3 4 + 5 * 6 -

后缀表达式较为常用,计算机熟悉的表达式,真狗。

后缀表达式(逆波兰表达式)是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。

三、中缀表达式转后缀表达式

这个有一个固定的思路,就像降龙十八掌秘籍一样,照着练就行了,如果你非要自创黯然销魂掌,你得自断一臂,不建议。

1、初始化两个栈:运算符栈s1和储存中间结果栈s2;

2、从右至左扫描中缀表达式;

3、遇到操作数时,将其压入s2;

4、遇到运算符时,比较其与s1栈顶运算符的优先级:

    (1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

    (2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;

    (3)否则,将s1栈顶的运算符弹出并压入s2中,再次转到(1),与s1中新的栈顶运算符相比较;

5、遇到括号时:

    (1)如果是左括号“(”,则直接压入s1;

    (2)如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;

6、重复步骤2至5,直到表达式的最右边

7、将s1中剩余的运算符依次弹出并压入s2;

8、依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式。

四、逆波兰计算器

大体思路:

1、中缀表达式转为后缀表达式,然后通过逆波兰计算器计算后缀表达式;

2、先将中缀表达式转为对应的List,方便运算 ;(3+4)* 5 - 6 转成 [(, 3, +, 4, ), *, 5, -, 6]

3、将list转为后缀表达式对应的list; [(, 3, +, 4, ), *, 5, -, 6] 转为 [3, 4, +, 5, *, 6, -]

4、完成逆波兰计算器

五、代码实现

package dataStructure.stack;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandNotation {
    public static void main(String[] args) {
        String expression = "(3+4)*5-6";//注意表达式
        List<String> infixExpressionList = toInfixExpressionList(expression);
        System.out.println("中缀表达式对应的List=" + infixExpressionList); // ArrayList [(, 3, +, 4, ), *, 5, -, 6]
        List<String> suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList);
        System.out.println("后缀表达式对应的List" + suffixExpreesionList); //ArrayList [3, 4, +, 5, *, 6, -]
        System.out.printf("expression=%d", calculate(suffixExpreesionList));
    }

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


    //方法:将得到的中缀表达式对应的List => 后缀表达式对应的List
    //即 ArrayList [(, 3, +, 4, ), *, 5, -, 6]  =》 ArrayList [3, 4, +, 5, *, 6, -]
    public static List<String> parseSuffixExpreesionList(List<String> ls) {
        //定义两个栈
        Stack<String> s1 = new Stack<String>(); // 符号栈
        //说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出
        //因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2
        //Stack<String> s2 = new Stack<String>(); // 储存中间结果的栈s2
        List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2
        //遍历ls
        for(String item: ls) {
            //如果是一个数,加入s2
            if(item.matches("\\d+")) {
                s2.add(item);
            } else if (item.equals("(")) {
                s1.push(item);
            } else if (item.equals(")")) {
                //如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
                while(!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                s1.pop();//!!! 将 ( 弹出 s1栈, 消除小括号
            } else {
                //当item的优先级小于等于s1栈顶运算符, 将s1栈顶的运算符弹出并加入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较
                //问题:我们缺少一个比较优先级高低的方法
                while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item) ) {
                    s2.add(s1.pop());
                }
                //还需要将item压入栈
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并加入s2
        while(s1.size() != 0) {
            s2.add(s1.pop());
        }
        return s2; //注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List
    }

    //完成对逆波兰表达式的运算
	/*
	 * 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,由此得出最终结果
	 */
    public static int calculate(List<String> ls) {
        // 创建给栈, 只需要一个栈即可
        Stack<String> stack = new Stack<String>();
        // 遍历 ls
        for (String item : ls) {
            // 这里使用正则表达式来取出数
            if (item.matches("\\d+")) { // 匹配的是多位数
                // 入栈
                stack.push(item);
            } else {
                // pop出两个数,并运算, 再入栈
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if (item.equals("+")) {
                    res = num1 + num2;
                } else if (item.equals("-")) {
                    res = num1 - num2;
                } else if (item.equals("*")) {
                    res = num1 * num2;
                } else if (item.equals("/")) {
                    res = num1 / num2;
                } else {
                    throw new RuntimeException("运算符有误");
                }
                //把res 入栈
                stack.push("" + res);
            }

        }
        //最后留在stack中的数据是运算结果
        return Integer.parseInt(stack.pop());
    }
}

//编写一个类 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("不存在该运算符" + operation);
                break;
        }
        return result;
    }

}

六、控制台输出

 

 

 

数据结构与算法(二)——前缀、中缀、后缀表达式 前缀、中缀、后缀表达式 及 中缀、后缀的转换(Scala版) 阅读详情

相关推荐

【尚硅谷】数据结构和算法——前缀、中缀、后缀表达式规则

1)前缀表达式又称波兰式,前缀表达式的运算符位于操作符之前。2)举例说明:(3+4)*5-6 对应的前缀表达式就是 - * + 3 4 5 6前缀表达式的计算机求值:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得到的值即为表达式的结果。例如:(3+4)*5-6 对应的前端表达式就是 - * + 3 4 5 6,针对前缀表达式求值步骤如下:1)从右到左。

weixin_54533016的博客 2918

中缀表达式转后缀表达式(逆波兰式)

中缀表达式转后缀表达式(逆波兰式)

qq_33300585的博客 6907

【算法】逆波兰式(后缀表达式)的计算 & 中缀表达式转后缀表达式(逆波兰式)

【算法】逆波兰式(后缀表达式)的计算 & 中缀表达式转后缀表达式(逆波兰式)

九师兄 2166

LeetCode刷题笔记day13-将普通表达式转化为逆波兰表达式

将中缀表达式转换为逆波兰式,如“8+(4-2)×5+12/2”,转换为逆波兰式为8 4 2-5 × + 12 2 / +,利用栈这种数据结构,先模拟下详细过程: ①、首先遍历字符串数组,第一个数据为8,为数字,直接输出,故此时输出结果res为res = 8 ②、此时遇到+号,非数字,且栈stack为空,则入栈,stack = + ③、遇到(,由于此时左括号优先级最高,故左括号入栈,此时stack = +( ④、遇到4,则直接输出此时res = 8 4 ⑤、遇到-号,因为此时栈顶元素为(,故将+号优先级提升至

Mark_able 1681

CODESYS开发实战:EtherCAT总线伺服从站配置与运动控制

本文详细介绍了在CODESYS平台上进行EtherCAT总线伺服从站配置与运动控制的实战教程。内容涵盖从设备描述文件安装、主从站拓扑构建,到核心的伺服使能状态机编程、过程数据映射,以及最终实现点位运动控制的完整流程。文章旨在帮助开发者快速掌握基于CODESYS的EtherCAT总线伺服控制技术,提升工业自动化项目开发效率。

weixin_29281915的博客 327

40分钟快速入门Dart基础(上)

针对final 和const 理解的有点模糊的可以参考这篇文章: 可以参考这里Flutter 知识梳理(Dart)-Dart中static final const 区别看是不是超级好上手,好操作~其实Dart的整个学习起来还是蛮简单的,对于有基础的老司机更简单一些。分分钟敲起来~这篇文章就简单的介绍到这里如何短时间快速入门Dart,避免入坑。由于是想让大家快速入门Flutter,所以针对上面的这些章节我们讲解的只是一些在开发Flutter 过程中常用的一些方法和函数。

qq_7813180 4569

【数据结构及算法】1.将表达式转换成逆波兰式

一、题目 ◆3.21③ 假设表达式由单字母变量和双目四则运算算符构成。试写一个算法,将一个通常书写形式且书写正确的表达式转换为逆波兰式。 实现下列函数:char *RPExpression(char *e);/* 返回表达式e的逆波兰式 */ Stack是一个已实现的栈。可使用的相关类型和函数:typedef char SElemType; // 栈Stack的元素类型Status Ini...

weixin_30241919的博客 2591

Calibre LVS效率翻倍秘籍:用Hierarchical Flow处理亿级晶体管设计的5个关键阶段

本文详细解析了如何利用Hierarchical Flow技术提升Calibre LVS在亿级晶体管SoC设计中的验证效率。通过五个关键阶段的分层验证流程,包括顶层抽象验证、模块级独立验证等,可显著降低内存占用40-60%,缩短迭代周期50-70%,特别适用于SMIC等先进工艺节点。文章还分享了算力资源优化、并行化处理等实战技巧,帮助工程师应对大规模芯片验证挑战。

sam99的博客 768

栈:中缀表达式转后缀表达式(逆波兰式)求值(支持多位数)【C语言,数据结构】(内含源代码)

设计并验证以下算法:首先将一个中缀表达式转换成逆波兰式(后缀表达式),然后对此逆波兰表达式求值。 需求分析: 1.输入分析:可能输入正确的和错误的表达式,可能输入超过一位的数字,输入的表达式可能产生浮点类型的结果,输入中空格可能出现在任何地方,输入由‘#’结尾。(现只输入整数) 2.演示程序在用户输入完整表达式后,若表达式不合法则输出相应提示,先输出用户表达式,再输出逆波兰表达式,最后输出其结果。 3.程序执行命令包括:(1)接受输入 (2)判断输入 (3)求逆波兰式 (4)根据逆波兰式求值

哦豁果奶的博客 1779

极验点选click3.1.0所对应fullpage.js的逆向分析

极验3代点选验证,本文适用于使用click.3.1.0.js和fullpage919-eyz9lh.js版本的web验证码,没有细节内容,适合有基础的开发者阅读。

shanf7921的博客 647

大模型微调部署实战及类GPT工具的高效使用

本文主要介绍了专栏《大模型微调部署实战及类GPT工具的高效使用》的核心内容,希望对使用大语言模型的同学们有所帮助。 文章目录 1. 前言 2. 专栏亮点 3. 你的收获 4. 详细目录

herosunly的博客 22万+

【数据结构与算法 7】中缀表达式转为后缀表达式

面试题文档来啦,内容很多,485页!由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。

2401_83817122的博客 1034

点云语义分割:PointNet训练S3DIS数据集

文章目录一、数据准备1.1、数据下载二、训练三、测试 项目地址:pointnet 此次我们是用pointnet网络来做语义分割。代码在pointnet项目中的sem_seg文件夹下,里面也有README.md介绍了训练的过程。 一、数据准备 1.1、数据下载 原始数据下载 处理好的h5格式数据下载 二、训练 三、测试 ...

zhaoguanhua的博客 4176

Java-数据结构系列十:逆波兰计算器(含中缀表达式转后缀表达式)

1.逆波兰表达式(后缀表达式)的计算过程: 例如:“(3+4)*5-6”对应的逆波兰表达式为“3 4 + 5 * 6 -”,针对后缀表达式使用栈求值的步骤: 从左至右扫描,将3和4压入堆栈; 遇到+运算符,弹出栈顶元素4和次顶元素3,计算3+4的值,得7后将7入栈; 将5入栈; 遇到*运算符,弹出7和5,计算乘积为35压入栈中; 将6入栈; 遇到-运算符,弹出栈顶元素和次顶元素,计算...

money_yao的博客 2161

QGIS003:【02标注工具栏】-标注的样式、放置和属性修改

摘要:文本介绍了QGIS标注的样式、放置和属性修改

qq_31762031的博客 1916

低代码部署与管理——OpenClaw智能助手的应用部署与运维(2026技术版)

OpenClaw智能助手的低代码部署与管理平台采用分层架构设计,包含部署工具、环境管理、版本控制等核心模块,支持从开发到生产的全流程自动化部署。该系统通过Docker、Kubernetes等技术实现应用构建和部署,利用Terraform等工具管理多环境配置,并提供完善的监控运维能力。平台针对开发、测试、预生产和生产环境提供差异化配置,确保部署效率和运行可靠性。这种架构设计遵循自动化、可扩展性和安全性原则,显著提升了智能助手应用的部署效率和运维质量。

一键难忘的博客 314

[ 数据结构与算法 ] 逆波兰计算器

逆波兰计算器 应用场景 输入一个逆波兰表达式(后缀表达式),使用栈(Stack), 计算其结果 支持小括号和多位数整数,因为这里我们主要讲的是数据结构,因此计算器进行简化,只支持 对整数的计算。 计算后缀表达式 案例: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 - , 针对后缀表达式求值 关键点:判断扫描到的字符串:1.数字直接入栈;2.若是运算符,出栈两个数字并计算,计算结果放回栈中 步骤如下: 1.从左至右扫描,将 3 和 4 压入堆栈; 2.遇到+运算符,因此弹出 4 和

jason_bone_的博客 2240

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

数据结构 - 中缀表达式转后缀表达式及逆波兰计算器实现

前言 前面实现了一个中缀表达式计算器:数据结构 - 栈、栈实现计算器 中缀表达式是我们平常书写的表达式1+((2+3)*4)-5,但不符合计算机的运算,所以我们设计计算器的时候异常的复杂,设计了数栈、符号栈以及多种规则才实现了简单的表达式计算 后缀表达式1 2 3 + 4 * + 5 -更符合计算机的运算,设计一个后缀表达式计算器 Java实现后缀表达式计算器 对于提供的一个后缀表达式3 4 + 5 * 6 -(默认空格分开),我们如何计算? 先把表达式分割成一个list[3, 4, +, 5, *,

key_768的博客 865

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

新星计划Day8【数据结构与算法】 栈Part2

新星计划Day8【数据结构与算法】 栈Part2 👩‍💻博客主页:京与旧铺的博客主页 ✨欢迎关注🖱点赞🎀收藏⭐留言✒ 🔮本文由京与旧铺原创,csdn首发! 😘系列专栏:java学习 👕参考网课:尚硅谷 💻首发时间:🎞2022年5月2日🎠 🎨你做三四月的事,八九月就会有答案,一起加油吧 🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦 🎧最后的话,作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲 🛒导航小助手🎪 文章目录新星计划Day8【数据结构与算法】 栈Part2🛒导航

qq_46272491的博客 2783

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

前缀、中缀、后缀表达式

qq_50233116的博客 7873

前缀,后缀表达式(逆波兰表达式),中缀表达式转为对应的后缀表达式,逆波兰计算器的实现(java)

波兰表达式1.前缀,中缀,后缀表达式规则介绍1.前缀表达式(波兰表达式) 1.前缀,中缀,后缀表达式规则介绍 1.前缀表达式(波兰表达式) 前缀表达式的运算符位于操作符之前 例如:(3+4)*5-6对应的前缀表达式就是== - * + 3 4 5 6== 前缀表达式的计算机求值 从左至右扫描表达式,遇到数字时就将数字压入堆栈,遇到运算符时弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素和次顶元素) 完成堆逆波兰表达式的运算 //完成对逆波兰表达式的运算 /* * 1)从左至右扫描,将3

m0_57105290的博客 931

【数据结构与算法】了解前缀中缀后缀表达式,实现逆波兰计算器

一、中缀表达式 1、中缀表达式就是常见的运算表达式,如(3+4)×5-6 2、中缀表达式的求值是我们人最熟悉的,但是对计算机来说却不好操作(前面我们讲的案例就能看的这个问题),因此,在计算结果时,往往会将中缀表达式转成其它表达式来操作(一般转成后缀表达式.) 中缀表达式的计算机求值 使用栈实现综合计算器的计算 思路 (1)通过一个 index 值(索引),来遍历我们的表达式 (2) 如果我们发...

像风走过八千里 656

数据结构与算法java - 07 中缀表达式 前缀表达式 后缀表达式 逆波兰表达式 逆波兰计算器 中缀表达式转为逆波兰表达式

前缀表达式 Prefix expression 波兰表达式,运算符都位于操作数之前 从右向左扫描表达式,遇到数字时,将数字压入堆栈;遇到运算符时,弹出栈顶的两个数,用运算符对他们做相应的计算(栈顶元素和次顶元素),并将结果入栈,重复上述过程直到表达式的最左端 举例:(3+4)×5-6 prefix expression: -×+3456 从右向左扫描,将 6,5,4,3 压入栈 遇到 + 弹出 3、4,计算 3+4 得到7,将 7 入栈 接下来是 ×,弹出 7、5,计算 7 × 5,将 3

shake_shark_pp 481
上一篇: 【数据结构与算法 6】栈实现综合计算器
下一篇: 数据结构与算法
哪 吒
哪 吒 2022年度博客之星TOP 1 2022年度博客之星TOP 1 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 59万+粉丝 2933原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值