Python栈案例:从零实现栈结构操作与实战解析
目录导读
- 栈数据结构核心概念 – 什么是栈?LIFO原则图解
- Python手动实现栈类 – 基于列表与链表两种方案
- 关键操作详解 – push、pop、peek、is_empty、size
- 四个经典案例实战 – 括号匹配、进制转换、网页后退、表达式求值
- 性能对比与最佳实践 – 列表 vs collections.deque
- 常见问题问答 – 面试高频考点解析
栈数据结构核心概念
栈(Stack)是一种受限的线性表,只允许在同一端进行插入和删除操作,这一端称为栈顶,另一端称为栈底,栈遵循后进先出(LIFO, Last In First Out)原则。

形象比喻:一叠盘子,你只能从最上面取盘子,也只能把新盘子放在最上面。
栈的核心特征
- 插入操作:入栈(push)
- 删除操作:出栈(pop)
- 栈顶访问:peek(查看但不移除)
- 所有操作的时间复杂度均为 O(1)
Python手动实现栈类
基于列表(list)实现
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() # 从尾部移除 = 出栈
raise IndexError("pop from empty stack")
def peek(self):
if not self.is_empty():
return self.items[-1]
raise IndexError("peek from empty stack")
def is_empty(self):
return len(self.items) == 0
def size(self):
return len(self.items)
基于collections.deque(双端队列)
from collections import deque
class StackDeque:
def __init__(self):
self.items = deque()
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def is_empty(self):
return len(self.items) == 0
def size(self):
return len(self.items)
性能提示:若只需栈操作,list足够高效;若需要频繁在两端操作,deque更优。
关键操作详解与时间复杂度
| 操作 | 描述 | 时间复杂度 |
|---|---|---|
push(x) |
将x压入栈顶 | O(1) |
pop() |
弹出并返回栈顶元素 | O(1) |
peek() |
返回栈顶元素但不移除 | O(1) |
is_empty() |
检查栈是否为空 | O(1) |
size() |
返回栈中元素个数 | O(1) |
注意:若使用list且栈顶在头部,则pop(0)的时间复杂度为O(n),因此永远选择在尾部操作。
四个经典案例实战
案例1:括号匹配检测
def is_balanced(expr):
stack = Stack()
mapping = {')': '(', ']': '[', '}': '{'}
for char in expr:
if char in mapping.values():
stack.push(char)
elif char in mapping:
if stack.is_empty() or stack.pop() != mapping[char]:
return False
return stack.is_empty()
print(is_balanced("({[]})")) # True
print(is_balanced("([)]")) # False
原理:遇到左括号入栈,遇到右括号与栈顶匹配。
案例2:十进制转二进制
def decimal_to_binary(num):
stack = Stack()
while num > 0:
stack.push(num % 2)
num //= 2
return ''.join(str(stack.pop()) for _ in range(stack.size()))
print(decimal_to_binary(10)) # 1010
原理:不断对2取余并压栈,最后依次弹出。
案例3:模拟浏览器后退功能
class BrowserHistory:
def __init__(self):
self.back_stack = Stack()
self.forward_stack = Stack()
self.current = None
def visit(self, url):
if self.current:
self.back_stack.push(self.current)
self.current = url
self.forward_stack = Stack() # 清空前进
def back(self):
if not self.back_stack.is_empty():
self.forward_stack.push(self.current)
self.current = self.back_stack.pop()
return self.current
def forward(self):
if not self.forward_stack.is_empty():
self.back_stack.push(self.current)
self.current = self.forward_stack.pop()
return self.current
案例4:中缀表达式转后缀(逆波兰)
def infix_to_postfix(expr):
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0}
stack = Stack()
output = []
for token in expr.split():
if token.isdigit():
output.append(token)
elif token == '(':
stack.push(token)
elif token == ')':
while not stack.is_empty() and stack.peek() != '(':
output.append(stack.pop())
stack.pop() # 移除 '('
else: # 运算符
while (not stack.is_empty() and
precedence[stack.peek()] >= precedence[token]):
output.append(stack.pop())
stack.push(token)
while not stack.is_empty():
output.append(stack.pop())
return ' '.join(output)
print(infix_to_postfix("3 + 5 * ( 2 - 8 )")) # 3 5 2 8 - * +
性能对比与最佳实践
| 实现方式 | 优点 | 缺点 |
|---|---|---|
list实现 |
简单直观,大多数场景足够 | 大量动态扩容时性能波动 |
deque实现 |
线程安全,内存连续,访问快 | 需要额外导入模块 |
| 链表实现 | 无容量限制,内存稳定 | 占用更多内存,非连续缓存不友好 |
推荐:对单线程常规场景,使用list实现;对多线程或极高性能场景,使用collections.deque,除非面试要求手写链表,否则不推荐自行实现链表栈。
常见问题问答
Q1: Python中列表为什么可以当栈用?
A: 因为list.append()和list.pop()在尾部操作的时间复杂度都是O(1),天然满足栈的LIFO特性,但需要注意不要用list.insert(0,x)避免O(n)操作。
Q2: 栈的深度有限制吗?
A: Python列表没有硬性限制,但受系统内存限制,递归调用时默认深度限制为1000,可通过sys.setrecursionlimit()调整。
Q3: 何时应该使用栈而非队列? A: 当问题具有回溯特性时(如括号匹配、路径搜索、撤销操作),优先用栈,若需先进先出则用队列。
Q4: 栈能否用于DFS(深度优先搜索)? A: 可以,DFS本质上就是栈的思想——深度穷举,标准DFS实现常用递归(隐式栈)或显式栈。
Q5: 为什么栈操作都是O(1)? A: 因为栈只在一端操作,每次操作直接作用在最后一个元素上,无需遍历其他元素,与数据量无关。
通过本文,你已掌握:
- 栈的LIFO核心原理
- Python中基于
list和deque的完整实现 - 4个经典实战案例(括号匹配、进制转换、浏览器后退、表达式转换)
- 性能选型建议与面试高频问答
栈是算法题中最基础也最强大的数据结构之一,建议读者动手运行以上代码,并尝试修改案例中的输入参数,观察栈结构在不同场景下的行为模式,掌握栈,你将能轻松应对回溯、深度优先搜索等复杂算法。