📅  最后修改于: 2023-12-03 14:51:37.765000             🧑  作者: Mango
堆栈是一种数据结构,它可用于在程序中管理函数调用、表达式求值、任务管理和许多其他用途。Python 核心语言并没有提供内置的堆栈数据类型,但是,使用 Python 的列表就可以轻松地实现堆栈。在本文中,我们将探讨堆栈的基本概念,以及 Python 中堆栈的实现和应用。
堆栈是一个后进先出(LIFO)数据结构,这意味着最后一个插入堆栈的元素最先移出堆栈。堆栈有两个主要操作:
push
:将一个元素添加到堆栈的顶部。
pop
:从堆栈的顶部移除最后添加的元素。
堆栈还具有许多其他操作,如查看堆栈的顶部元素(但不移除它)和确定堆栈是否为空。
Python 中的列表可以用于实现堆栈。例如,以下代码创建一个空的堆栈:
stack = []
要将元素推入堆栈,可以使用 append()
方法,如下所示:
stack.append(1)
stack.append(2)
stack.append(3)
这将在堆栈的顶部添加三个元素。现在,如果使用 pop()
方法,可以按逆序从堆栈中移除元素:
stack.pop() # 输出 3
stack.pop() # 输出 2
stack.pop() # 输出 1
在上面的代码中,pop()
方法从堆栈的顶部移除每个元素,并将其返回。最后一个 pop()
的调用将从堆栈中移除最后添加的元素(即 $3$)并将其返回。stack
现在为空列表,因为它不包含任何元素。
下面是堆栈在 Python 中的几个常见应用:
堆栈可用于求解表达式并评估其值。例如,考虑以下中缀表达式:
$$ 2 + 3 \times 4 - 5 $$
在求解此表达式时,可以使用两个堆栈:一个用于操作符,另一个用于操作数。从左到右扫描表达式,将所有操作数推入操作数堆栈。当遇到运算符时,将其与操作符堆栈的顶部元素进行比较。如果新运算符的优先级低于或等于堆栈顶部运算符的优先级,则从操作数堆栈中弹出两个操作数,并使用堆栈顶部的运算符对它们进行计算。然后将计算结果推入操作数堆栈中。例如,以下代码使用堆栈求解上述表达式:
def evaluate_expression(expression):
operators = []
operands = []
for token in expression.split():
if token.isdigit():
operands.append(int(token))
else:
while operators and precedence(operators[-1]) >= precedence(token):
apply_operator(operators, operands)
operators.append(token)
while operators:
apply_operator(operators, operands)
return operands[0]
def precedence(operator):
if operator in '+-':
return 1
elif operator in '*/':
return 2
else:
return 0
def apply_operator(operators, operands):
operator = operators.pop()
right_operand = operands.pop()
left_operand = operands.pop()
result = evaluate(left_operand, operator, right_operand)
operands.append(result)
def evaluate(left_operand, operator, right_operand):
if operator == '+':
return left_operand + right_operand
elif operator == '-':
return left_operand - right_operand
elif operator == '*':
return left_operand * right_operand
else:
return left_operand / right_operand
expression = "2 + 3 * 4 - 5"
result = evaluate_expression(expression)
print(result) # 输出 9
在 Python 中,每次调用函数时,都会创建一个新的堆栈帧,并将其推入调用堆栈中。当函数返回时,堆栈帧将从调用堆栈中弹出,并将控制返回到调用方。例如,以下代码定义了两个函数 foo()
和 bar()
,并演示了函数调用堆栈:
def foo():
print("foo() 开始")
bar()
print("foo() 结束")
def bar():
print("bar() 开始")
print("bar() 结束")
foo()
输出结果如下:
foo() 开始
bar() 开始
bar() 结束
foo() 结束
在此示例中,调用 foo()
会创建一个新的堆栈帧,并将其推入调用堆栈中。在 foo()
中调用 bar()
会创建另一个堆栈帧,并将其推入调用堆栈的顶部。当 bar()
返回时,它的堆栈帧将从调用堆栈中弹出,并将控制返回到 foo()
。最后,当 foo()
返回时,它的堆栈帧也将从调用堆栈中弹出,并将控制返回到脚本的主体。
堆栈可用于管理用户的撤销和重做操作。例如,用户对文档进行编辑时,可以将每个操作存储在堆栈中以便撤销或重做。以下代码演示了如何使用堆栈实现简单的撤销和重做功能:
class Editor:
def __init__(self):
self.document = ""
self.command_stack = []
self.undo_stack = []
def insert(self, text):
self.document += text
self.command_stack.append(('insert', text))
self.undo_stack.clear()
def delete(self):
if not self.document:
return
deleted_char = self.document[-1]
self.document = self.document[:-1]
self.command_stack.append(('delete', deleted_char))
self.undo_stack.clear()
def undo(self):
if not self.command_stack:
return
last_command = self.command_stack.pop()
if last_command[0] == 'insert':
self.document = self.document[:-len(last_command[1])]
else:
self.document += last_command[1]
self.undo_stack.append(last_command)
def redo(self):
if not self.undo_stack:
return
last_undo = self.undo_stack.pop()
if last_undo[0] == 'insert':
self.document += last_undo[1]
else:
self.document = self.document[:-len(last_undo[1])]
self.command_stack.append(last_undo)
editor = Editor()
editor.insert("Hello ")
editor.insert("world!")
print(editor.document) # 输出 "Hello world!"
editor.delete()
print(editor.document) # 输出 "Hello "
editor.undo()
print(editor.document) # 输出 "Hello world!"
editor.redo()
print(editor.document) # 输出 "Hello "
在此示例中,Editor
类封装了文档及其编辑操作。insert()
方法向文档添加文本,并将新的 ('insert', text)
命令推入 command_stack
。delete()
方法从文档中删除最后一个字符,并将新的 ('delete', deleted_char)
命令推入 command_stack
。undo()
方法从 command_stack
弹出最后一个命令,并反转其影响。具体来说,如果该命令是 ('insert', text)
,则将文档中的文本删除以撤消命令。如果命令是 ('delete', deleted_char)
,则向文档中添加字符以撤消命令。每个撤销操作将已撤销的命令推入 undo_stack
。redo()
方法从 undo_stack
弹出最后一个命令,并重新执行它。具体来说,如果该命令是 ('insert', text)
,则将文本添加到文档中。如果命令是 ('delete', deleted_char)
,则从文档中删除字符。每个重做操作将已重做的命令推入 command_stack
。