玩转python:掌握Python数据结构之栈Stack
栈(Stack)是计算机科学中一种非常基础且重要的数据结构。它的特点是后进先出(LIFO,Last In First Out),就像我们生活中叠盘子一样,最后放上去的盘子总是最先被拿走。本文将用通俗易懂的语言和丰富的案例,带你轻松掌握栈的概念、实现和应用。
什么是栈?
栈是一种线性数据结构,它只允许在一端进行数据的插入和删除操作。这一端被称为栈顶(Top),另一端被称为栈底(Bottom)。栈的操作主要有两种:
- 入栈(Push):将数据放入栈顶。
- 出栈(Pop):从栈顶取出数据。
栈的典型特点是后进先出,也就是说,最后入栈的数据会最先出栈。
生活中的栈
为了更好地理解栈,我们可以从生活中找到许多栈的例子:
-
叠盘子:
- 当你洗完盘子后,会把盘子一个一个叠起来。最后放上去的盘子总是最先被拿走。
- 这就是栈的“后进先出”特性。
-
浏览器的返回按钮:
- 当你浏览网页时,每次点击一个新链接,浏览器都会将当前页面压入栈中。
- 当你点击返回按钮时,浏览器会从栈顶弹出上一个页面。
- 这就是栈的“入栈”和“出栈”操作。
-
撤销操作:
- 在文本编辑器中,每次编辑操作(如输入文字、删除文字)都会被记录到栈中。
- 当你按下撤销键时,编辑器会从栈顶弹出最近的操作并撤销。
- 这就是栈的“后进先出”特性。
栈的实现
在Python中,栈可以通过列表(List)或链表(Linked List)来实现。下面我们用列表来实现一个简单的栈。
1. 使用列表实现栈
class Stack:
def __init__(self):
self.items = [] # 用列表存储栈中的数据
# 入栈操作
def push(self, item):
self.items.append(item) # 将数据添加到列表末尾(栈顶)
# 出栈操作
def pop(self):
if not self.is_empty(): # 如果栈不为空
return self.items.pop() # 弹出列表末尾的数据(栈顶)
return None # 如果栈为空,返回None
# 查看栈顶元素
def peek(self):
if not self.is_empty(): # 如果栈不为空
return self.items[-1] # 返回列表末尾的数据(栈顶)
return None # 如果栈为空,返回None
# 判断栈是否为空
def is_empty(self):
return len(self.items) == 0 # 如果列表为空,栈为空
# 返回栈的大小
def size(self):
return len(self.items) # 返回列表的长度
# 打印栈的内容
def print_stack(self):
print("栈顶 ->", self.items, "<- 栈底")
# 使用栈
stack = Stack()
stack.push(1) # 入栈
stack.push(2)
stack.push(3)
stack.print_stack() # 输出: 栈顶 -> [1, 2, 3] <- 栈底
print(stack.pop()) # 输出: 3(出栈)
stack.print_stack() # 输出: 栈顶 -> [1, 2] <- 栈底
print(stack.peek()) # 输出: 2(查看栈顶元素)
栈的应用案例
栈在计算机科学中有广泛的应用,以下是几个常见的案例:
1. 浏览器的返回功能
浏览器的返回功能可以用栈来实现。每次访问一个新页面时,将当前页面压入栈中;点击返回按钮时,从栈顶弹出上一个页面。
class Browser:
def __init__(self):
self.back_stack = Stack() # 后退栈
self.forward_stack = Stack() # 前进栈
# 访问新页面
def visit(self, page):
self.back_stack.push(page) # 将当前页面压入后退栈
self.forward_stack = Stack() # 清空前进栈
print(f"访问页面: {page}")
# 后退
def back(self):
if self.back_stack.size() > 1: # 如果后退栈中有多个页面
current_page = self.back_stack.pop() # 弹出当前页面
self.forward_stack.push(current_page) # 将当前页面压入前进栈
previous_page = self.back_stack.peek() # 查看上一个页面
print(f"后退到页面: {previous_page}")
else:
print("无法后退")
# 前进
def forward(self):
if not self.forward_stack.is_empty(): # 如果前进栈不为空
next_page = self.forward_stack.pop() # 弹出下一个页面
self.back_stack.push(next_page) # 将下一个页面压入后退栈
print(f"前进到页面: {next_page}")
else:
print("无法前进")
# 使用浏览器
browser = Browser()
browser.visit("首页")
browser.visit("关于我们")
browser.visit("联系我们")
browser.back() # 输出: 后退到页面: 关于我们
browser.forward() # 输出: 前进到页面: 联系我们
2. 文本编辑器的撤销功能
文本编辑器的撤销功能可以用栈来实现。每次编辑操作(如输入文字、删除文字)都会被记录到栈中;按下撤销键时,从栈顶弹出最近的操作并撤销。
class TextEditor:
def __init__(self):
self.content = "" # 当前文本内容
self.undo_stack = Stack() # 撤销栈
# 输入文字
def type(self, text):
self.undo_stack.push(self.content) # 将当前内容压入撤销栈
self.content += text # 更新内容
print(f"当前内容: {self.content}")
# 撤销
def undo(self):
if not self.undo_stack.is_empty(): # 如果撤销栈不为空
previous_content = self.undo_stack.pop() # 弹出上一个内容
self.content = previous_content # 恢复内容
print(f"撤销后内容: {self.content}")
else:
print("无法撤销")
# 使用文本编辑器
editor = TextEditor()
editor.type("Hello") # 输出: 当前内容: Hello
editor.type(" World") # 输出: 当前内容: Hello World
editor.undo() # 输出: 撤销后内容: Hello
3. 括号匹配检查
栈可以用来检查表达式中的括号是否匹配。例如,检查 ((a + b) * (c - d))
中的括号是否正确配对。
def is_balanced(expression):
stack = Stack() # 创建一个栈
for char in expression:
if char == "(": # 如果是左括号,压入栈
stack.push(char)
elif char == ")": # 如果是右括号
if stack.is_empty(): # 如果栈为空,说明没有匹配的左括号
return False
stack.pop() # 弹出栈顶的左括号
return stack.is_empty() # 如果栈为空,说明括号匹配
# 检查括号是否匹配
print(is_balanced("((a + b) * (c - d))")) # 输出: False
print(is_balanced("((a + b) * (c - d)")) # 输出: True
4. 计算后缀表达式
栈可以用来计算后缀表达式(也称为逆波兰表达式)。例如,计算 3 4 + 5 *
的值。
def evaluate_postfix(expression):
stack = Stack() # 创建一个栈
for token in expression.split(): # 将表达式按空格分割
if token.isdigit(): # 如果是数字,压入栈
stack.push(int(token))
else: # 如果是运算符
operand2 = stack.pop() # 弹出第二个操作数
operand1 = stack.pop() # 弹出第一个操作数
if token == "+":
stack.push(operand1 + operand2)
elif token == "-":
stack.push(operand1 - operand2)
elif token == "*":
stack.push(operand1 * operand2)
elif token == "/":
stack.push(operand1 / operand2)
return stack.pop() # 返回最终结果
# 计算后缀表达式
print(evaluate_postfix("3 4 + 5 *")) # 输出: 35
总结
栈是一种简单但功能强大的数据结构,它的“后进先出”特性在计算机科学中有广泛的应用。通过本文的学习,你应该已经掌握了栈的基本概念、实现方法以及常见应用场景。无论是浏览器的返回功能、文本编辑器的撤销功能,还是括号匹配检查和后缀表达式计算,栈都能提供高效的解决方案。
希望本文能帮助你更好地理解栈,并在实际编程中灵活运用!