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

news2024/10/6 14:30:03

前缀表达式的计算机求值

注意:在前缀表达式中,遇到运算符时,如“-”,是栈顶元素 - 次顶元素

中缀表达式

后缀表达式

 注意:在后缀表达式中,遇到运算符时,如“-”,是次顶元素 - 栈顶元素

逆波兰计算器

思路如后缀表达式中的第二张图所示

代码实现如下:

# 用数组模拟栈
class ArrayStack:
    def __init__(self, size):
        self.max_size = size  # 栈的最大容量
        self.top = -1  # top 表示栈顶
        self.stack = []  # 用列表表示数组

    # 判断栈满
    def is_full(self):
        return self.top == self.max_size - 1

    # 判断栈空
    def is_empty(self):
        return self.top == -1

    # 入栈
    def push(self, ele):
        if self.is_full():
            print("栈已满")
        else:
            self.top += 1
            self.stack.insert(self.top, ele)

    # 出栈
    def pop(self):
        if self.is_empty():
            print("栈空")
        else:
            val = self.stack.pop(self.top)
            self.top -= 1
            return val


# 实现逆波兰表达式
def poland(expression: str):
    # 以空格分割输入的逆波兰表达式
    str_list = expression.split(" ")

    # 创建操作数栈
    num_stack = ArrayStack(len(str_list))

    operator = {
        "+": lambda x, y: x + y,
        "-": lambda x, y: x - y,
        "*": lambda x, y: x * y,
        "/": lambda x, y: x / y
    }
    # 从左往右遍历逆波兰式列表
    for i in str_list:
        try:
            i = float(i)
            # 遇到数字将其压入操作数栈
            num_stack.push(float(i))
        except Exception:  # 遇到运算符弹出两个操作数进行运算,并将结果压入数栈
            # 弹出两个操作数,注意是 次顶元素 运算符(如 -) 栈顶元素
            num2 = num_stack.pop()
            num1 = num_stack.pop()
            res = operator[i](num1, num2)
            if res:
                # 将运算结果压入栈
                num_stack.push(res)
            else:
                raise ValueError("不支持运算符{}".format(i))

    print("运算结果为:", num_stack.pop())


poland("3 4 + 5 * 6 -")
poland("4 5 * 8 - 60 + 8 2 / +")

中缀表达式转后缀表达式

思路分析

示意图

例子:将中缀表达式:1+((2+3)* 4)-5  转为后缀表达式: 1 2 3 + 4 * + 5 - 

代码实现 

# 用数组模拟栈
class ArrayStack:
    def __init__(self, size):
        self.max_size = size  # 栈的最大容量
        self.top = -1  # top 表示栈顶
        self.stack = []  # 用列表表示数组

    # 判断栈满
    def is_full(self):
        return self.top == self.max_size - 1

    # 判断栈空
    def is_empty(self):
        return self.top == -1

    # 入栈
    def push(self, ele):
        if self.is_full():
            print("栈已满")
        else:
            self.top += 1
            self.stack.insert(self.top, ele)

    # 出栈
    def pop(self):
        if self.is_empty():
            print("栈空")
        else:
            val = self.stack.pop(self.top)
            self.top -= 1
            return val

    # 查看栈顶元素
    def get_top(self):
        if self.is_empty():
            print("栈空")
        else:
            return self.stack[self.top]


# 中缀表达式转后缀表达式
class InfixToPostfix:
    def __init__(self, size):
        # 1、初始化两个栈 s1, s2
        self.s1 = ArrayStack(size)
        self.s2 = ArrayStack(size)

    def is_high_priority(self, oper1, oper2):
        """判断 oper1 的优先级是否大于 oper2,是返回 True"""
        priority_dict = {
            '+': 0,
            '-': 0,
            '*': 1,
            '/': 1
        }

        prio1 = priority_dict.get(oper1)
        prio2 = priority_dict.get(oper2)
        if prio1 is None:
            raise ValueError('不支持运算符' + oper1)
        if prio2 is None:
            raise ValueError('不支持运算符' + oper2)

        return prio1 > prio2

    def infix2postfix(self, infix_exp: str) -> list:
        """将中缀表达式转为后缀表达式返回"""
        # 将中缀表达式字符串转换为列表
        infix_list = self.str_to_list(infix_exp)

        # 2、从左往右遍历中缀表达式,即遍历列表的每一个元素 ele
        for ele in infix_list:
            # 3、遇到的元素 ele 是数字,直接压入栈 s2
            if '0' <= ele <= '9':
                self.s2.push(ele)
            # 4、遇到的元素 ele 是运算符,按以下三种情况处理:
            elif ele != '(' and ele != ')':
                while True:
                    # 4.1、如果栈 s1 为空,或者 s1 栈顶为左括号 ( ,则直接将元素 ele 压入栈 s1
                    if self.s1.is_empty() or self.s1.get_top() == '(':
                        self.s1.push(ele)
                        break
                    # 4.2、如果不满足4.1,则比较元素 ele 和 s1 栈顶元素的优先级,
                    #       如果 ele 优先级大于 s1 栈顶元素,则直接将元素 ele 压入栈 s1
                    elif self.is_high_priority(ele, self.s1.get_top()):
                        self.s1.push(ele)
                        break
                    # 4.3、如果不满足4.1、4.2,则弹出 s1 栈顶元素压入 s2,
                    #       然后回到 4.1 步重新判断元素 ele 和 s1 栈顶元素的关系
                    else:
                        self.s2.push(self.s1.pop())
            # 5、遇到的元素 ele 是左括号 ( ,直接压入栈 s1
            elif ele == '(':
                self.s1.push(ele)
            # 6、遇到的元素 ele 是右括号 ) ,依次弹出 s1 元素,并将弹出的元素压入 s2,
            #       直到弹出的元素是 左括号 ( ,则停止弹出 s1 元素,并且将弹出的左括号丢弃,不压入栈 s2
            else:
                val = self.s1.pop()
                while val != '(':
                    self.s2.push(val)
                    val = self.s1.pop()

        # 7、重复步骤2-6,直到列表遍历完毕,将栈 s1 剩余的元素依次弹出压入栈 s2 ,
        #       此时栈 s2 中的元素,从栈底到栈顶的顺序就是得到的后缀表达式
        while not self.s1.is_empty():
            self.s2.push(self.s1.pop())
        result = []
        # 依次弹出 s2 栈顶元素,并添加到列表 result 中
        while not self.s2.is_empty():
            result.append(self.s2.pop())
        # 将列表 result 反转,得到的才是后缀表达式
        result.reverse()
        return result

    def str_to_list(self, infix_expression: str) -> list:
        """将中缀表达式字符串转换为列表"""
        # 将字符串转换为列表,并去除字符串中的空格
        infix_list = [i for i in infix_expression if i != ' ']

        # 遍历列表,将多位数合并成一个字符串
        i = 0
        while i < len(infix_list):
            val = infix_list[i]
            # 如果该元素是数字
            if '0' <= val <= '9':
                next = infix_list[i + 1] if i + 1 < len(infix_list) else None
                # 判断列表的下一个元素是不是数字,是的话说明是多位数,需要进行拼接
                while next and '0' <= next <= '9':
                    val += next  # 拼接数字
                    infix_list.pop(i + 1)  # 并从列表中移除下一位数字
                    # 继续判断下一个元素是不是数字,如果是还需要继续拼接
                    next = infix_list[i + 1] if i + 1 < len(infix_list) else None
                # 将拼接好的多位数赋值给i,即列表中遇到的多位数的第一个数字的位置
                infix_list[i] = val
            i += 1

        return infix_list  # 返回转换后的中缀表达式列表


# 1+((2+3)* 4)-5 转为后缀表达式: 1 2 3 + 4 * + 5 -
s = '1+((2+3)* 4)-5'
infix_to_postfix = InfixToPostfix(len(s))
print(infix_to_postfix.infix2postfix(s))  # 1 2 3 + 4 * + 5 -

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

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

相关文章

【Docker】实现JMeter分布式压测

一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试。如本网站所示&#xff0c;一个JMeter实例将能够控制许多其他的远程JMeter实例&#xff0c;并对你的应用程序产生更大的负载。JMeter使用Java RMI[远程方法调用]来与分布式网络中的对象进行交互。JMeter主站…

Springboot 实践(14)spring config 配置与运用--手动刷新

前文讲解Spring Cloud zuul 实现了SpringbootAction-One和SpringbootAction-two两个项目的路由切换&#xff0c;正确访问到项目中的资源。这两个项目各自拥有一份application.yml项目配置文件&#xff0c;配置文件中有一部分相同的配置参数&#xff0c;如果涉及到修改&#xf…

ajax实现百度一下模糊查询功能

1、效果 如下图所示&#xff0c;我们在输入大学时&#xff0c;程序会到后端查询名字中包含大学的数据&#xff0c;并展示到前端页面。 用户选择一个大学&#xff0c;该大学值会被赋值到input表单&#xff0c;同时关闭下拉表单&#xff1b; 当页面展示的数据都不符合条件时&…

【软考】系统架构设计师 - 知识扩展 - “区块链技术“

目录 一 简介&#x1f451; 1 比特币❤️ 2 区块链的特点❤️ 3 共识算法❤️ 二 练习题&#x1f451; 三 扩展&#x1f451; 1 哈希算法❤️ 2 哈希指针❤️ 3 UTXO❤️ 4 参考资料❤️ 一 简介&#x1f451; 1 比特币❤️ 比特币底层采用了区块链技术。 比特币交易…

android在java代码里面运行shell脚本,使用shell脚本杀死目标进程

android开发中使用shell脚本的比较少&#xff0c;即使使用也是在adb里面直接运行&#xff0c;但是今天我就记录一下怎么在java里面执行shell脚本。 注意&#xff1a;这个需要配置selinux权限&#xff0c;或者你可以直接把selinux权限关闭才能运行 一、写一个shell脚本 这里我…

npm publish包报404,is not in the npm registry错误

1. 指定发布目标2. 登录npm&#xff0c;使用登录名发布包&#xff0c;包名命名原则“登录名/包名”&#xff0c;或 “包名” 3. 删除某一个版本npm unpublish pvfhv/eslint-config-prettier1.0.1 --force 删除后的版本不能重复使用&#xff0c;正式解释&#xff1a; Unfortun…

蓝桥杯官网练习题(凑算式)

类似填空题&#xff1a; ①算式900&#xff1a; https://blog.csdn.net/s44Sc21/article/details/132746513?spm1001.2014.3001.5501https://blog.csdn.net/s44Sc21/article/details/132746513?spm1001.2014.3001.5501 ②九宫幻方③七星填数④幻方填空&#xff1a;https:/…

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改

目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…

PHP表单token验证防CSRF攻击

在PHP中&#xff0c;表单token是一种安全机制&#xff0c;用于防止跨站请求伪造&#xff08;CSRF&#xff09;攻击。 CSRF攻击是一种利用用户身份在未经授权的情况下执行非法操作的攻击方式。 表单token的原理是在表单中生成一个随机的token&#xff0c;并将其存储在服务器端…

第 2 章 线性表 (线性表的静态单链表存储结构(一个数组只生成一个静态链表)实现)

1. 背景说明 A { c, b, e, g, f, d }B { a, b, n, f } 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H#define CHECK_RET(ret) if (ret ! RET_OK) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n&…

【Redis】Lua脚本在Redis中的基本使用及其原子性保证原理

文章目录 背景一、Eval二、EvalSHA三、Redis 对 Lua 脚本的管理3.1 script flush3.2 script exists3.3 script load3.4 script kill 四、Lua在Redis中原子性执行的原理 背景 Lua 本身是一种轻量小巧的脚本语言&#xff0c;在Redis2.6版本开始引入了对Lua脚本的支持。通过在服务…

高并发环境下压测故障

文章目录 一、高并发压测故障二、JVM 调优1. 堆内存调优2. 堆外内存调优 一、高并发压测故障 每次在大促之前&#xff0c;我们都需要对服务进行压测。而在压测期间&#xff0c;突然爆发了红灯告警&#xff0c;订单量直接少了一半&#xff0c;这是一次很严重的压测故障。首先看…

公司快递账单管理智能化教程

今时不同往日&#xff0c;企业寄件早已摆脱纸质面单&#xff0c;向更为便捷的电子面单过渡。众快递公司为了留住大客户&#xff0c;为其提供更好的服务&#xff0c;早早推出月结模式寄件。办公族应该不陌生&#xff0c;企业如果和快递公司签订月结协议的话&#xff0c;员工寄件…

SEO扫地僧站群·静态生成式养站王,万站秒建,批量养站神器介绍

扫地僧站群静态养站王,程序采用了"织梦CMS"式静态生成式的方式&#xff0c;只需要一个后台管理系统即可管理多个网站&#xff0c;大大提高了建站效率,程序可以适配各种采集器获得的内容&#xff0c;可以方便地实现内容的快速采集,程序支持实时统计和广告插入&#xf…

leetcode刷题--栈与递归

文章目录 1. 682 棒球比赛2. 71 简化路径3. 388 文件的最长绝对路径4. 150 逆波兰表达式求值5. 227. 基本计算器II6. 224. 基本计算器7. 20. 有效的括号8. 636. 函数的独占时间9. 591. 标签验证器10. 32.最长有效括号12. 341. 扁平化嵌套列表迭代器13. 394.字符串解码 1. 682 棒…

docker 部署vue

1&#xff1a; 首先部署nginx docker run --name nginx -d -p 88:80 nginx 2&#xff1a;访问 http://xxxxxxx:88/ 3: 进入nginx docker exec -it nginx /bin/sh 4: 回到vs&#xff0c;编译项目 npm run build 得到dist文件夹 5&#xff1a;创建docker 6&#xff1a; 将…

量化交易最新12篇顶会论文及开源代码汇总(WWW23、AAAI23、KDD23)

对比普通的交易方式&#xff0c;量化交易具有高效性、稳定性以及强风险控制能力&#xff0c;因此&#xff0c;量化交易在金融领域中已经得到了广泛的应用&#xff0c;目前已有许多大型投资机构和对冲基金将量化交易列为其投资组合的重要部分。 本次分享的是我从各大顶会中精选…

826. 安排工作以达到最大收益;2257. 统计网格图中没有被保卫的格子数;816. 模糊坐标

826. 安排工作以达到最大收益 核心思想&#xff1a;排序维护最大利润。首先我们需要对工人按照能力排序&#xff0c;前面工人满足的最大利润后面的工人肯定是满足的&#xff0c;所以我们只需要用一个tmp来维护小于等于当前工人的最大利润&#xff0c;然后如何得到tmp&#xff…

java.lang.Exception: No runnable methods

无可执行test方法异常&#xff0c;报错为&#xff1a; 1.查看是否添加了Test注解在执行的方法上 2.查看测试类的注解 3.查看test类的导包&#xff0c;一定要是junit的。

【SpringMVC】RESTful风格CRUD实现

目录 一、REST简介 1.1 什么是REST? 1.2 REST风格的优点 1.3 请求方式 二、构建项目 ⭐思路分析 2.1 环境准备 2.1.1 导入相关pom依赖 2.1.2 jdbc.properties&#xff1a;配置文件 2.1.3 配置代码生成器 generatorConfig.xml 2.1.4 spring与mybatis整合的配置文件 s…