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

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

本文将深入探讨栈的应用和实现。我们将介绍栈在括号匹配、函数调栈、逆波兰表达式求值和中缀表达式转换为逆波兰表达式中的应用,并提供使用列表和链表实现栈的示例。

栈应用

1. 括号匹配

栈可以用于检查括号是否匹配。我们可以遍历字符串中的每个字符,如果是左括号,则将其压入栈中;如果是右括号,则将其与栈顶元素进行匹配。如果匹配成功,则将栈顶元素弹出;否则,字符串不合法。

下面是一个示例,用于演示如何使用栈检查括号是否匹配。

def is_valid_parentheses(s):
    stack = []
    mapping = {')': '(', '}': '{', ']': '['}
    for char in s:
        if char in mapping:
            top_element = stack.pop() if stack else '#'
            if mapping[char] != top_element:
                return False
        else:
            stack.append(char)
    return not stack

在这个示例中,我们定义了一个is_valid_parentheses()函数,它接受一个字符串作为返回一个布尔值,表示括号是否匹配。我们使用栈来存储左括号,并使用一个字典来存储左右括号之间的映射关系。我们遍历字符串中的每个字符如果是左括号,则将其压入栈中;如果是右括号,则将其与栈顶元素进行匹配。如果匹配,则将栈元素弹出;否则,字符串不合法。最后,如果栈为空,则表示括号匹配成功。

2. 函数调用栈

在Python中,每次函数调用都创建一个新的栈帧。栈帧包含函数的局部变量、参数和返回地址等信息。当函数返回时,栈帧被弹出,控权返回到调用函数的位置。

下面是一个示例,用于演示函数调用栈的工作原理。

def foo():
    print('foo')
    bar()

def bar():
    print('bar')

foo()

在这个示例中,我们定义了两个函数foo()和bar(),并在foo()函数中调用了bar()函数。当我们运行这个时,Python会创建一个新的栈帧存储foo()函数的局部变量、参数和返回地址等信息。然后,foo()函数调用bar()函数,Python会创建另一个栈帧来存储bar()函数的局部变量、参数和返回地址等信息。当bar()函数返回时,Python会弹出bar()函数的栈帧,并将控制权返回到foo()函数。最后,当foo()函数返回时,Python会弹出foo()函数的帧,并将控制权返回到主程序。

3. 逆波兰表达式求值

逆波兰表达式是一种不需要括号的数学表达式表示方法。在逆波兰表达式中,操作符在操作数的后面,而不是在操作数的中间。例如,表达式“2 + 3”可以写成“2 3 +”。

我们可以栈来求解逆波兰表达式。我们遍历表达式中的每个元素,如果元素是操作数,则将其压入栈中;如果元素是操作符,则从栈中弹出两个操作数,并将它们应用于操作符。最后,栈中剩下的元素就是表达式的值。

下面是一个示例,用于演示如何栈实现逆波兰表达式求值。

def eval_rpn(tokens):
    stack = []
    for in tokens:
        if token in ['+', '-', '*', '/']:
            b = stack.pop()
            a = stack.pop()
            if token == '+':
                stack.append(a + b)
            elif token == '-':
                stack.append(a - b)
            elif token == '*':
                stack.append(a * b)
            elif token == '/':
                stack.append(int(a / b))
        else:
            stack.append(int(token))
    return stack.pop()

在这个示例中,我们定义了一个eval_rpn()函数,它接受一个逆波兰表达式作为参数,并返回表达式的值。我们使用一个栈来存储操作数,并遍历表达中的每个元素。如果元素是操作符,则从栈中弹出两个操作数,并将它们应用于操作符。如果元素是操作数,则将其压入栈中。最后,栈中剩下的元素就是表达的值。

4. 中缀表达式转换为逆波兰表达式

中缀表达式是我们通常使用的数学表达式表示方法。在中缀表达式中,操作符在操作数的中间,而不是在操作数的后面。例如,表达式“2 + 3”就是一个中缀表达式。

我们可以使用栈将中缀表达式转换为逆波兰表达式。我们遍历表达式中的每个元素,如果元素是操作数,则将其添加到列表中;如果元素是操作符,则将其与栈顶元素进行比较。如果栈顶元素的优先级大于或等于当前操作符的优先级,则将栈顶元弹出并添加到输出中。最后,我们将剩余的运算符弹出并添加到输出列表中。

下面是一个示例,用于演示如何使用栈实现中缀表达式转换为逆波兰表达式。

def infix_to_rpn(expr):
    stack = []
    output = []
    precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
    for token in expr:
        if token.isdigit():
            output.append(token)
        elif token in ['+', '-', '*', '/']:
            while stack and stack[-1] != '(' and precedence[token] <= precedence.get(stack[-1], 0):
                output.append(stack.pop())
            stack.append(token)
        elif token == '(':
            stack.append(token)
        elif token == ')':
            while stack and stack[-1] != '(':
                output.append(stack.pop())
            stack.pop()
    while stack:
        output.append(stack.pop())
    return output

在这个示例中,我们定义了一个infix_to_rpn()函数,它接受一个中缀表达式作为参数,并返回一个波兰表达式。我们使用一个栈来存储运算符,并遍历表达式中的每个元素。如果元素是操作数,则将添加到输出列表中。如果元素是操作符,则将其与栈顶元素进行比较。如果栈顶元素的优先级大于或等于当前操作符的优先级,则将栈顶元弹出并添加到输出列表。最后,我们将剩余的运算符弹出并添加到输出列表中。

栈实现

1. 使用列表实现栈

在Python中,我们可以使用列表来实现栈。列表的append()方法可以用于将元素压入栈中,而pop()方法可以用于弹出栈顶元素。

下面是一个示例,用于演示如何使用列表实现栈。

class Stack:
    def __init__(self):
        self.items = []

    def is_empty(self):
        return not bool(self.items)

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[-1] if self.items else None

    def size(self):
        return len(self.items)

在这个示例中,我们定义了一个Stack类,它包含_empty()、push()、pop()、peek()和size()等方法。我们使用一个列表来存储栈中的元素。is_empty()方法用于检查栈是否为空;push()方法于将元素压入中;pop()方法用于弹出栈顶元素;peek()方法用于返回栈顶元素size()方法用于返回栈的大小。

2. 使用链表实现栈

在Python中,我们也可以使用链表来实现栈。链表的头部可以用于存储栈顶元素,而每个可以用于存储元素和下一个节点的引用。

下面是一个示例,用于演示如何使用链表实现栈。

class Node:
    def __init__(self, data=None):
        self.data = data
        self.next = None

class Stack:
    def __init__(self):
        self.top = None

    def is_empty(self):
        return not bool(self.top)

    def push(self, data):
        new_node = Node(data)
        new_node.next = self.top
        self.top = new_node

    def pop(self):
        if self.top:
            data = self.top.data
            self.top = self.top.next
            return data
        else:
            return None

    def peek(self):
        return self.top.data if self.top else None

    def size(self):
        count = 0
        current = self.top
        while current:
            count += 1
            current = current.next
        return count

在这个示例中,我们定义了一个Node类,它包含一个数据属性和一个下一个节点的引用。我们还定义了一个Stack类,包含一个头部节点。is_empty()方法用于检查栈是否为空;push()方法用于将元素压入栈;pop()方法用于弹出栈顶元素;peek()方法用于返回栈顶元素;size()方法用于栈的大小。

结论

本文深入探讨了栈的应用和实现。我们介绍了栈在括号匹配、函数调用、逆波兰表达式求值和中缀表达式转换为逆波兰表达式中的应用,并提供使用列表和链表实现栈的示例。在实际应用中,我们可以根据具体的问题选择不同的栈实现方式结合其他数据结构和算法进行合处理,实现复杂的计算任务的求解。

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

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

相关文章

  • 使用jupyter notebook将文件保存为Markdown,HTML等文件格式

    使用Jupyter Notebook将文件保存为Markdown、HTML等文件格式 Jupyter Notebook是一种交互式笔记本,可以用于数据分析、可视化、机器学习等。在Jupyter Notebook中,我们可以将笔记本中的内容保存为Markdown、HTML等文件格式,方便我们进行分享和展示。本文将详细讲解如何使用Jupyter Notebook…

    python 2023年5月15日
    00
  • Python字符串格式化常用手段及注意事项

    Python字符串格式化是Python中常见的操作之一。通过字符串格式化,可以将多个值按照一定的格式以字符串的形式输出。下面是Python字符串格式化的常用手段和注意事项。 格式化字符串 Python提供了多种方式格式化字符串,主要有两种: 使用百分号(%)方式 可以使用百分号(%)来格式化一个字符串。如下所示: name = ‘Alice’ age = 2…

    python 2023年6月5日
    00
  • 字节跳动2019春招研发部分python编程题汇总

    下面我将详细讲解“字节跳动2019春招研发部分python编程题汇总”的完整攻略,过程中包含两条示例说明。 概述 “字节跳动2019春招研发部分python编程题汇总”包含15道Python编程题,难度不等,需要掌握Python基础和常见算法,具有较高的考察难度和实际工作中Python编程能力的要求。 准备工作 在开始做题前,需要准备好Python的开发环境…

    python 2023年5月13日
    00
  • 详解Python 字典表达式

    Python 字典表达式是一种有用的语言特性,它允许开发者快速以简洁且易于阅读的方式构建字典。本攻略将详细介绍 Python 字典表达式的使用方法。 什么是 Python 字典表达式 Python 字典表达式是一种便于创建和初始化字典的语法。它的语法形式为 {key1: value1, key2: value2, …},其中键值对用逗号分隔。这种语法非常…

    python-answer 2023年3月25日
    00
  • 在 python 中使用 networkx 包的 K-最短路径

    【问题标题】:K-shortest paths using networkx package in python在 python 中使用 networkx 包的 K-最短路径 【发布时间】:2023-04-06 07:18:01 【问题描述】: 我使用 osmnx 包创建了荷兰高速公路的多向图。 该图是从 osmnx 返回的多向图。由于我有兴趣计算起点和终点…

    Python开发 2023年4月6日
    00
  • matplotlib画图之修改坐标轴刻度问题

    下面是关于“matplotlib画图之修改坐标轴刻度问题”的完整攻略。 修改坐标轴刻度问题 在使用Matplotlib进行可视化绘制时,我们可能会遇到需要修改坐标轴刻度的需求,比如想要自定义坐标轴上的刻度大小、标签内容或者刻度间隔等等。下面将给出两条示例,分别介绍如何实现这些操作。 示例一:自定义坐标轴刻度大小和标签 在Matplotlib中,默认的坐标轴刻…

    python 2023年5月18日
    00
  • Python 依赖库太多了该如何管理

    Python依赖库太多了该如何管理 在本攻略中,我们将介绍如何管理Python依赖库,以便更好地管理项目中的依赖关系。我们将介绍如何使用虚拟环境、pip工具和requirements.txt文件来管理Python依赖库。 步骤1:使用虚拟环境 使用虚拟环境可以帮助我们在不同的项目之间隔离Python依赖库。使用以下代码可以创建一个虚拟环境: python -…

    python 2023年5月15日
    00
  • 如何在 Python 中单击按钮时更改按钮颜色

    【问题标题】:How to change button color while it is being clicked in Python如何在 Python 中单击按钮时更改按钮颜色 【发布时间】:2023-04-05 09:50:01 【问题描述】: 我正在使用 tKinter 模块在 Python 中制作带有按钮的 GUI。我有一个与背景融为一体的按钮…

    Python开发 2023年4月5日
    00
合作推广
合作推广
分享本页
返回顶部