数据结构与算法-(7)---栈的应用拓展-前缀表达式转换+求值

简介: 数据结构与算法-(7)---栈的应用拓展-前缀表达式转换+求值

回顾+思路讲解

之前我们介绍过了什么是后缀表达式,以及它如何通过中缀表达式进行转换,以及关于后缀表达式的求值问题,如有遗忘👉🔗http://t.csdnimg.cn/Hl4Y9

今天我们拓展一下,前缀表达式的转换和求值问题

💫中缀转后缀表达式的思路:

从左到右扫描逐个字符扫描中缀表达式的过程中,采用一个栈来暂存未处理的操作符
这样,栈顶的操作符就是最近暂存进去的,当遇到一个新的操作符,就需要跟栈顶的操作符比较下优先级,再行处理--->新符号和栈顶对比,新的高,就入栈(因为取时也先取);       新的低,就把栈顶出栈,让栈顶的先运算

想要了解具题后缀的相关知识点点击👉🔗http://t.csdnimg.cn/9100K

中缀转前缀思路也类似,不过

中缀表达式中运算符的优先级和结合性需要考虑,从左往右扫描的话,需要对每个运算符的优先级和结合性进行判断,才能决定是否需要先进行计算。这样会增加算法的复杂度。

从右往左扫描,则可以利用栈的特性,遇到运算符时先将其压入栈中,再比较栈顶运算符的优先级和结合性,来决定是否需要先进行计算。这样可以简化算法,提高效率。另外,从右往左扫描还可以处理右结合性的运算符。

参考后缀表达式代码思路:

我们利用一个栈来进行中缀表达式转前缀表达式的操作。其中prec{}是一个字典,用于记录操作符的优先级,优先级由低到高依次为1~3。opStack是我们初始化的操作符栈,prefixList是用于储存前缀表达式的空列表。

我们首先将中缀表达式解析为一个tokenList列表,并反转该列表,这样我们就可以正向扫描这个列表。

在扫描过程中,对于每个操作数token,我们需要分别处理三种情况:

  1. 操作数--将其添加到前缀表达式列表prefixList中。
  2. 右括号--将其压入操作符栈opStack中。
  3. 左括号--从操作符栈opStack中弹出并返回顶部元素topToken,直到遇到右括号为止。期间,将所有弹出的操作符添加到前缀表达式列表prefixList中。

对于第4种情况---操作符,

我们需要通过while循环语句比较操作符的优先级。

如果当前操作符的优先级小于等于栈顶操作符的优先级,我们就将栈顶操作符弹出并添加到前缀表达式列表prefixList中。然后将当前操作符压入操作符栈opStack中

(1)中缀表达式转前缀

class Stack :
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def push(self,item):
        self.items.append(item)
    def pop(self):
        return  self.items.pop()
    def peek(self):
        return self.items[len(self.items) - 1]
    def size(self):
        return len(self.items)
def infix_to_prefix(infix_expr):
    # 定义一个空字典prec{}--记录操作符优先级  -- 优先级由低到高是1~3
    prec = {}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec[")"] = 1
    opStack = Stack()#初始化操作符栈
    #初始化列表用于储存前缀表达式
    prefixList = []
    #将中缀表达式解析为一个 tokenList 列表,并反转该列表
    tokenList = infix_expr.split()[::-1]#利用split切割成一个一个,然后通过切片转置到列表里
    #列表的元素为:c +  ) B + A (  遇到右括号入栈,左计算
    for token in tokenList:
        #若token是操作数---添加到列表
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            prefixList.append(token)
        # )---压入操作符栈
        elif token == ")":
            opStack.push(token)
        # (---从操作符栈opStack中弹出并返回顶部元素topToken
        elif token == "(":
            topToken = opStack.pop()
            #当topToken不是")"
            while topToken != ")":
                prefixList.append(topToken)
                topToken = opStack.pop()
        # 若token是操作符,通过while循环语句比较他们的优先级,大的操作符添加到式子末端
        else:
            while (not opStack.isEmpty()) and \
                    (prec[opStack.peek()] > prec[token]):
                        #opStack.pop()会直接把栈顶元素弹出并返回
                        prefixList.append(opStack.pop())
            opStack.push(token)
#扫描完后将栈中的元素弹出
    while not opStack.isEmpty():
        #  操作符
        prefixList.append(opStack.pop())
        #  将后缀表达式通过切片转置合成前缀表达式字符串
    return " ".join(prefixList[::-1])
print(infix_to_prefix("A + B * C "))

(2) 前缀表达式求值

def postfix_eval(prefix_expr):
    operandStack = Stack()
    tokenList = prefix_expr.split()
    for token in reversed(tokenList):
        if token in "0123456789":#遇到操作数,入栈
            operandStack.push(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token,operand1,operand2)
            operandStack.push(result)
    return operandStack.pop()
def doMath(op, op1, op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2
print(doMath("*", 11, 11))

定义两个函数:postfix_eval()doMath()

postfix_eval()函数接受一个前缀表达式,将其转换为后缀表达式并计算结果。

在计算过程中,它先将操作数入栈,然后遇到运算符就弹出栈顶的两个元素进行计算,并将计算结果重新入栈。最终,栈中仅剩下一个元素,即表达式的计算结果。

doMath()函数用于执行基本的数学运算,包括加、减、乘、除。

程序的最后一行在调用doMath()函数,并输出结果。用于计算11乘以11的结果。

 

目录
相关文章
|
7月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
412 86
|
8月前
|
存储 监控 JavaScript
基于布隆过滤器的 Node.js 算法在局域网电脑桌面监控设备快速校验中的应用研究
本文探讨了布隆过滤器在局域网电脑桌面监控中的应用,分析其高效空间利用率、快速查询性能及动态扩容优势,并设计了基于MAC地址的校验模型,提供Node.js实现代码,适用于设备准入控制与重复数据过滤场景。
287 0
|
7月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
390 3
|
7月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
|
7月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
7月前
|
机器学习/深度学习 算法 安全
小场景大市场:猫狗识别算法在宠物智能设备中的应用
将猫狗识别算法应用于宠物智能设备,是AIoT领域的重要垂直场景。本文从核心技术、应用场景、挑战与趋势四个方面,全面解析这一融合算法、硬件与用户体验的系统工程。
611 0
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习模型、算法与应用的全方位解析
深度学习,作为人工智能(AI)的一个重要分支,已经在多个领域产生了革命性的影响。从图像识别到自然语言处理,从语音识别到自动驾驶,深度学习无处不在。本篇博客将深入探讨深度学习的模型、算法及其在各个领域的应用。
1578 3
|
9月前
|
机器学习/深度学习 人工智能 算法
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
|
9月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
510 1
|
8月前
|
算法 数据可视化
matlab版本粒子群算法(PSO)在路径规划中的应用
matlab版本粒子群算法(PSO)在路径规划中的应用

热门文章

最新文章