Python数据结构与算法中的栈详解(3)

Python数据结构与算法中的栈详解(3)

在前两篇文章中,我们介绍了栈的基本概念、实现方式和应用场景。在本篇文章中,将深入探讨栈的一些高级应用,包中缀表达式转后缀表达式、后缀表达式求值和括号匹配等。

中缀表达式转后缀表达

中缀表达式是我们平常使用的表达式,例如3 + 4 * 5。但是,中缀表达式不方便计算机进行计算,因此我们需要将中缀表达式转换为后缀表达式。缀表达式也称为逆波兰表达式,它的计算方式更加方便。例如,上面的中缀表达式可以转换为后缀表达式3 4 5 * +

下面是中缀表达式后缀表达式的算法:

  1. 初始化一个空栈和一个空列表。
  2. 从左到右扫描中缀表达式的每个素。
  3. 如果当前元素是数字,将其添加到输出列表中。
  4. 如果当前元素是左括号,将其压入栈中。
  5. 如果当前元素是右括号,则将栈中的元素弹出并添加到输出列表中,直到遇到左括号。左括号不添加到列表中。
  6. 如果当前元素是运算符,比较其与栈顶运算符的优先级:
  7. 如果栈顶运算符优级较高或相等,则将其弹出并添加到输出列表中,直到栈为空或栈顶运算符优先级较低。
  8. 将当前运算符压入栈中。
  9. 如果中缀表达式扫描完毕,但栈中仍有运算符,将它们依次弹出并添加到输出列表中。
  10. 输出列表中的元素就是后缀表达式。

下面是一个示例,演示如何将中缀表达式3 + 4 * 5转换为后缀表达式:

  1. 初始化一个空栈和一个空列表。
  2. 从左到右描中缀表达式的每个元素。
  3. 3是数字,将其添加到输出列表中。
  4. +是运算符,将其压入栈中。
  5. 4是数字,其添加到输出列表中。
  6. *是运算符,比较其与栈顶运算符的优先级,栈顶运算符+优先级较低,将*压入栈中。
  7. 5是数字,将其添加到输出中。
  8. 中缀表达式扫描完毕,但栈中仍有运算符,将它们依次弹出并添加到输出列表中。栈中只有一个运算符*,其弹出并添加到输出列表中。
  9. 输出列表中的元素就是后缀表达式3 4 5 * +

下面是Python代码实现中缀表达式转后缀表达式:

def infix_to_postfix(infix_expr):
    # 运算符优先级
    prec = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
    # 初始化一个空栈和空列表
    op_stack = []
    postfix_list = []
    # 将中缀表达式转换为列表
    infix_list = infix_expr.split()

    for token in infix_list:
        if token.isdigit():
            # 如果当前元素是数字,将其添加到输出列表中
            postfix_list.append(token)
        elif token == '(':
            # 如果当前元素是左括号,将其压入栈中
            op_stack.append(token)
        elif token == ')':
            # 如果当前元素是右括号,则将栈中的元素弹出并添加到输出列表中,直到遇到左括号
            top_token =_stack.pop()
            while top_token != '(':
                postfix_list.append(top_token)
                top_token = op_stack.pop()
        else:
            # 如果当前元素是运算符
            while op_stack and prec[op_stack[-1]] >= prec[token]:
                # 比较其与栈顶运算符的优先级
                postfix_list.append(op_stack.pop())
            op_stack.append(token)

    # 将栈中剩余的运算符弹出并添加输出列表中
    while op_stack:
        postfix_list.append(op_stack.pop())

    # 输出列表中的元素就是后缀表达式
    return ' '.join(postfix_list)

后缀表达式求值

后表达式的计算方式更加方便,可以使用栈来实现。下面是后缀表达式求值的算法:

  1. 初始化一个空栈。
  2. 从左到右扫描后缀表达式的每个元素。
    3 如果当前元是数字,将其压入栈中。
  3. 如果当前元素是运算符,弹出栈顶的两个元素,进行运,并将结果压入栈中。
  4. 扫描完毕后,栈中只剩下一个元素,即为后缀表达式的计算结果。

下面是一个示例,演示如何计算后缀表达式3 4 5 * +的值:

  1. 初始化一个空栈。
  2. 从左到右扫描后缀表达式的每个元素。
  3. 3是数字,将压入栈中。
  4. 4是数字,将其压入栈中。
  5. 5是数字,将其压入栈中。
    -*是运算,弹出栈顶的两个元素45,进行运算4 * 5 = 20,并将结果20`压入栈中。
  6. +是运算符,弹出栈顶的两个元素320,进行运算3 + 20 = 23,并将结果23`压入栈中。
  7. 扫描完毕后,栈中只剩下一个元素23,即为后缀表达式的计算结果。

下面是Python代码实现后缀表达式求值:

def postfix_eval(postfix_expr):
    # 初始化一个空栈
    operand_stack = []
    # 将后缀表达式转换为列表    postfix_list = postfix_expr.split()

    for token in postfix_list:
        if token.isdigit():
            # 如果当前元素是数字,将其压入栈中
            operand_stack.append(int(token))
        else:
            # 如果当前元素是运算符,弹出栈顶的两个元素,进行运算,并将结果压入栈中
            operand2 = operand_stack.pop()
            operand1 = operand_stack.pop()
            result = do_math(token, operand1, operand2)
            operand_stack.append(result)

    # 栈中只剩下一个元素,即为后缀表达式的计算结果
    return operand_stack.pop()

def do_math(op, op1, op2):
    if op == '*':
        return op1 * op2
    elif op == '/':
        return op1 / op2
    elif op == '+':
        return op1 + op2
    else:
        return op1 - op2

括号匹配

括号匹配是栈的一个经典应用。我们可以使用栈来判断一个字符串中的括号是否匹配。下面是括号匹配的算法:

  1. 初始化一个空栈。
  2. 从左到右扫描字符串中的每个字符。
  3. 如果当前字符是左括号,将其压入栈中。
    4.当前字符是右括号,弹出栈顶元素。如果栈顶元素不是相应的左括号,则括号不匹配。
  4. 扫描完毕,如果栈为空,则括号匹配。

下面是一个示例,演示如何判断字符串((()))中的括号是否匹配:

  1. 初始化一个空栈。
  2. 从左到右扫描字符串中的每个字符。
  3. (是左括号,将其压入栈中。
  4. (是左括号,将其压入栈中。
  5. (是左括号,将其压入栈中。
  6. )是右括号,弹出栈顶元素(
  7. )是右括号,弹出栈顶元素(
  8. 是右括号,弹出栈顶元素(`。
  9. 扫描完毕后,如果栈为空,则括号匹配。

下是Python代码实现括号匹配:

def par_checker(symbol_string):
    # 初始化一个空栈
    s = Stack()

    for symbol in symbol_string        if symbol == '(':
            # 如果当前字符是左括号,将其压入栈中
            s.push(symbol)
        else:
            # 如果当前字符是右括号,弹出栈顶元素。如果栈顶元素不是相应的左号,则括号不匹配
            if s.is_empty():
                return False
            else:
                s.pop()

    # 扫描完毕后,如果栈为空,则括号匹配
    return s.is_empty()

示例说明

下面是两个示例,演示如何使用栈实现中缀表达式转后缀表达式和后缀表达式求值:

示例1:中缀表达式转后缀表达式

def infix_to_postfix(infix_expr):
    # 运算符优先级
    prec = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
    # 初始化一个空栈和一个空列表
    op_stack = []
    postfix_list = []
    # 将中缀表达式转换为列表
    infix_list = infix_expr.split()

    for token in infix_list:
        if token.isdigit():
            # 如果当前元素是数字,将其添加到输出列表中
            postfix_list.append(token)
        elif token == '(':
            # 如果当前元素是左括号,将其压入栈中
            op_stack.append(token)
        elif token == ')':
            # 如果当前元素是右括号,则将栈中的元素弹出并添加到列表中,直到遇到左括号
            top_token = op_stack.pop()
            while top_token != '(':
                postfix_list.append(top_token)
                top_token = op_stack.pop()
        else:
            # 如果当前元素是运算符
            while op_stack and prec[op_stack[-1]] >= prec[token]:
                # 比较其与栈顶运算符的优先级
                postfix_list.append(op_stack.pop())
            op_stack.append(token)

    # 将栈中剩余的运算符弹出并添加到输出列表中
    while op_stack:
        postfix_list.append(op_stack.pop())

    # 输出列表中的元素就是后缀表达式
    return ' '.join(postfix_list)

infix_expr = '3 + 4 * 5'
postfix_expr = infix_to_postfix(infix_expr)
print(postfix_expr)  # 输出:3 4 5 * +

在个示例中,我们使用栈实现了中缀表达式转后缀表达式。我们将中缀表达式3 + 4 * 5转换为后缀表达式3 4 5 * +

示例2:后缀表达式求

def postfix_eval(postfix_expr):
    # 初始化一个空栈
    operand_stack = []
    # 将后缀表达式转换为列表
    postfix_list = postfix_expr.split()

    for token in postfix_list:
        if token.isdigit():
            # 如果当前元素是数字,将其压入栈中
            operand_stack.append(int(token))
        else:
            # 如果当前元素是运算符,弹出栈顶的两个元素,进行运算,并将结果压入栈中
            operand2 = operand_stack.pop()
            operand1 = operand_stack.pop()
            result = do_math(token, operand1, operand2)
            operand_stack.append(result)

    # 栈中只剩下一个元素,即为后缀表达式的计算结果
    return operand_stack.pop()

def do_math(op, op1, op2):
    if op == '*':
        return op1 * op2
    elif op == '/':
        return op1 / op2
    elif op == '+':
        return op1 + op2
    else:
        return op1 - op2

postfix_expr = '3 4 5 * +'
result = postfix_eval(post_expr)
print(result)  # 输出:23

在这个示例中,我们使用栈实现了后缀表达式求值。我们计算后缀表达式3 45 * +的值,结果为23

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python数据结构与算法中的栈详解(3) - Python技术站

(0)
上一篇 2023年5月14日
下一篇 2023年5月14日

相关文章

  • Python实现的朴素贝叶斯分类器示例

    以下是关于“Python实现的朴素贝叶斯分类器示例”的完整攻略: 简介 朴素贝叶斯分类器是一种常用的机器学习算法,用于分类和预测。在本教程中,我们将介绍如何使用Python实现一个朴素贝叶斯分类器,包括数据预处理、特征提取、模型训练和预测等步骤。 原理 朴素贝叶斯分类器是一种基于贝叶斯定理的分类器,它假设特征之间相互独立,从而简化了计算。在本教程中,我们将使…

    python 2023年5月14日
    00
  • Python – 如何使用 PySAL 计算交互式空间自相关 (Moran I)?

    【问题标题】:Python – How do I compute interactive spatial autocorrelation (Moran I) using PySAL?Python – 如何使用 PySAL 计算交互式空间自相关 (Moran I)? 【发布时间】:2023-04-04 11:05:01 【问题描述】: 我在 PostgreSQ…

    Python开发 2023年4月6日
    00
  • python实现域名系统(DNS)正向查询的方法

    Python实现DNS正向查询攻略 在Python中进行DNS正向查询的方法分为以下几个步骤: 导入socket库:DNS查询需要使用到socket库,首先需要导入该库。 python import socket 构建查询请求:查询请求需要指定要查询的域名和查询类型。查询类型通常为A记录,其对应的数字为1。构建查询请求的方法如下: python def qu…

    python 2023年6月6日
    00
  • 利用Python实现自动扫雷小脚本

    利用Python实现自动扫雷小脚本的攻略如下: 一、思路 使用Python获取窗口句柄,并将窗口切换到扫雷程序窗口,以便后续的操作; 获取扫雷程序的界面信息,包括雷区大小、雷数以及每个格子的位置、大小等信息; 利用图像处理技术识别雷区中每个格子的状态(是雷、数字还是空白),并执行相应的操作; 不断循环以上步骤,直到游戏结束。 二、操作步骤 安装必要的Pyth…

    python 2023年5月19日
    00
  • python实现邻接表转邻接矩阵

    具体实现邻接表转邻接矩阵的过程,可以分为以下几个步骤: 第一步,定义邻接表 首先需要定义一个邻接表,一般来说邻接表是一个字典类型,字典的每一个键表示图中的一个节点,而该键对应的值则是与该节点相邻的所有节点。 例如,我们可以使用如下的邻接表表示一个简单无向图: adj_list = { ‘A’: [‘B’, ‘C’], ‘B’: [‘A’, ‘C’, ‘D’]…

    python 2023年6月3日
    00
  • 跟老齐学Python之集成开发环境(IDE)

    下面我来详细讲解如何在跟老齐学Python的学习过程中,配置适用于Python的集成开发环境(IDE)。主要分以下几步: 一、安装Python环境并配置环境变量 下载Python安装包并安装,建议使用Python3或Python3以上版本; 配置Python的环境变量,将Python的安装路径加入到系统环境变量中; 打开命令行工具,输入“python”,出现…

    python 2023年5月18日
    00
  • 详解Python PIL ImageSequence.Iterator()

    Python PIL库中的ImageSequence.Iterator()是一个非常有用的函数,它允许您从给定的动画图像中获取帧序列,同时提供访问动画帧之间的时间间隔的功能。 以下是使用Python PIL库中的ImageSequence.Iterator()的完整攻略: 1. 导入PIL库 在开始使用ImageSequence.Iterator()之前,必…

    python-answer 2023年3月25日
    00
  • python读取excel指定列数据并写入到新的excel方法

    下面我将详细讲解Python读取Excel指定列数据并写入到新的Excel方法的完整实例教程。 准备工作 在开始之前,我们需要先安装一些必要的包: pandas:数据分析库,提供快速、灵活且富有表现力的数据结构,目的是为了让数据的清洗、转换、分析工作快速、简单、有表现力。 openpyxl:操作Excel的一个Python库,可以读取和写入Excel文档。 …

    python 2023年5月13日
    00
合作推广
合作推广
分享本页
返回顶部