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

yizhihongxing

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中的__new__()方法的使用

    详解Python中的__new__()方法的使用 在Python中,__new__()方法是一个特殊的方法,用于创建对象并返回它。它是在__init__()方法之前调用的,用于创建实例并返回它。以下是Python中__new__()方法的详细解释: __new__()方法的基本用法 __new__()方法是一个类方法,用于创建一个新的实例。它的第一个参数是类…

    python 2023年5月14日
    00
  • Python常用断言函数实例汇总

    Python常用断言函数实例汇总的完整攻略 在Python中,我们可以使用断言函数来检查代码的正确性。断言函数会在代码中检查一个条件是否为真,如果条件为假,则会抛出一个异常。在文中,我们将详细讲解Python常用的断言函数,包括assert、assertEqual、assertTrue、assertFalse、In、assertNotIn等。 assert函…

    python 2023年5月13日
    00
  • Python生成器以及应用实例解析

    Python生成器是一种使用延迟计算来优化性能的函数。生成器通过yield语句,将复杂的数据结构惰性地逐项输出,从而减少内存需求和计算时间,实现了高效的数据处理。在本文中,我们将详细讲解Python生成器的语法和应用实例,展示其在编程过程中的重要性和实用性。 Python生成器的语法 生成器函数 Python生成器通常通过函数实现。生成器函数与普通函数的区别…

    python 2023年6月3日
    00
  • 让python同时兼容python2和python3的8个技巧分享

    以下是让python同时兼容python2和python3的8个技巧分享的详细攻略: 1. 引入__future__模块 在Python 2中,可以使用__future__模块来使用Python 3中的特性,这样可以提高代码在Python 2和Python 3之间的兼容性。在Python 2的顶部加入以下代码: from __future__ import …

    python 2023年6月3日
    00
  • python+pygame实现代码雨(黑客帝国既视感)

    Python 是一种面向对象、解释型计算机编程语言,它拥有简洁易读的语法、强大的可扩展性、支持多种平台等优势。Pygame 是一个 Python 模块,专门用于制作 2D 游戏。通过 Python 和 Pygame 的组合,我们可以实现代码雨的效果。 实现代码雨的步骤如下: 安装 Pygame 模块 pip install pygame 导入必要的函数库以及…

    python 2023年5月31日
    00
  • python K近邻算法的kd树实现

    以下是关于“Python K近邻算法的kd树实现”的完整攻略: 简介 K近邻算法是一种常用的分类算法,它通过计算样本之间的距离来确定最近的K个邻居,并使用它们的标签来预测新样本的标签。kd树是一种常用的数据结构,它可以加速K近邻算法的计算。本教程将介绍如何使用Python实现K近邻算法的kd树实现,并提供两个示例。 K近邻算法 K近邻算法是一种常用的分类算法…

    python 2023年5月14日
    00
  • Python爬虫解析网页的4种方式实例及原理解析

    Python爬虫是一种自动化程序,可以模拟人类浏览器行为,从网页中提取数据。在爬虫过程中,解析网页是非常重要的一步。本文将介绍Python爬虫解析网页的4种方式,包括正则表达式、BeautifulSoup、XPath和CSS选择器,并提供两个示例。 1. 正则表达式解析网页 正则表达式是一种用于匹配字符串的工具,可以用于解析网页。以下是一个示例,演示如何使用…

    python 2023年5月15日
    00
  • Python调用微信公众平台接口操作示例

    下面我将详细讲解“Python调用微信公众平台接口操作示例”的完整攻略: 1. 准备工作 在开始使用微信公众平台接口之前,您需要进行以下操作: 注册微信公众号,并获取公众号的APPID和APPSECRET。 将服务器IP地址添加到公众号的IP白名单中,以确保可以正常连接微信服务器。 此外,您还需要安装Python的Requests库以便对微信接口进行网络请求…

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