Python数据结构综合应用:实战案例与练习
Python数据结构综合应用:实战案例与练习
一、数据结构回顾
本周学习的核心数据结构及其Python实现方式如下:
数据结构 | 特点 | Python实现示例 |
---|---|---|
列表(List) | 有序,可修改,动态数组 | my_list = [1, 2, 3] |
元组(Tuple) | 有序,不可修改 | my_tuple = (1, 2, 3) |
栈(Stack) | LIFO(后进先出) | 使用列表的append() 和pop() |
队列(Queue) | FIFO(先进先出) | 使用collections.deque |
双向链表 | 快速插入/删除 | 自定义节点类实现 |
哈希表 | O(1)时间复杂度查找 | 字典dict 类型 |
二叉搜索树 | 左子树值 < 根 < 右子树值 | 自定义树节点类 |
图(Graph) | 节点与边的集合 | 字典表示邻接表 |
二、实战案例解析
案例1:LRU缓存实现
需求场景
设计一个最近最少使用缓存,当容量达到上限时淘汰最久未使用的数据。
实现方案
class DLinkedNode:
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.cache = {}
self.capacity = capacity
self.head, self.tail = DLinkedNode(), DLinkedNode()
self.head.next = self.tail
self.tail.prev = self.head
def _add_node(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def _remove_node(self, node):
prev = node.prev
next = node.next
prev.next = next
next.prev = prev
def _move_to_head(self, node):
self._remove_node(node)
self._add_node(node)
def get(self, key: int) -> int:
if key not in self.cache:
return -1
node = self.cache[key]
self._move_to_head(node)
return node.value
def put(self, key: int, value: int) -> None:
if key in self.cache:
node = self.cache[key]
node.value = value
self._move_to_head(node)
else:
if len(self.cache) >= self.capacity:
last = self.tail.prev
self._remove_node(last)
del self.cache[last.key]
new_node = DLinkedNode(key, value)
self.cache[key] = new_node
self._add_node(new_node)
关键设计
- 哈希表:快速定位节点位置
- 双向链表:维护访问顺序,头节点存放最近访问元素
案例2:Dijkstra最短路径算法
算法步骤
- 初始化距离字典,起点距离为0,其他为无穷大
- 使用优先队列存储未处理的节点
- 每次取出距离最小的节点
- 更新相邻节点的最短距离
Python实现
import heapq
def dijkstra(graph, start):
distances = {vertex: float('infinity') for vertex in graph}
distances[start] = 0
pq = [(0, start)]
while pq:
current_dist, current_vertex = heapq.heappop(pq)
if current_dist > distances[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
distance = current_dist + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return distances
# 示例图结构(邻接表)
graph = {
'A': {'B': 6, 'D': 1},
'B': {'A': 6, 'C': 5},
'C': {'B': 5, 'D': 8, 'E': 4},
'D': {'A': 1, 'C': 8, 'E': 3},
'E': {'C': 4, 'D': 3}
}
print(dijkstra(graph, 'A')) # 输出各节点到A的最短距离
三、综合练习题
1. 无序数组转二叉搜索树
class TreeNode:
def __init__(self, val=0):
self.val = val
self.left = None
self.right = None
def sorted_array_to_bst(nums):
if not nums:
return None
mid = len(nums) // 2
root = TreeNode(nums[mid])
root.left = sorted_array_to_bst(nums[:mid])
root.right = sorted_array_to_bst(nums[mid+1:])
return root
# 使用示例
unsorted = [3, 1, 4, 5, 2]
sorted_arr = sorted(unsorted)
bst_root = sorted_array_to_bst(sorted_arr)
2. 有效括号表达式验证
def is_valid_expression(s: str) -> bool:
stack = []
brackets = {')': '(', ']': '[', '}': '{'}
for char in s:
if char in brackets.values():
stack.append(char)
elif char in brackets:
if not stack or stack[-1] != brackets[char]:
return False
stack.pop()
return not stack and any(c in '+*-/' for c in s) # 确保包含运算符
print(is_valid_expression("(a+b)*c")) # True
print(is_valid_expression("((a+b))")) # False(缺少运算符)
3. 图中所有路径查找
def find_all_paths(graph, start, end, path=[]):
path = path + [start]
if start == end:
return [path]
if start not in graph:
return []
paths = []
for node in graph[start]:
if node not in path:
newpaths = find_all_paths(graph, node, end, path)
for p in newpaths:
paths.append(p)
return paths
# 示例图结构
graph = {
'A': ['B', 'C'],
'B': ['D'],
'C': ['D'],
'D': ['E'],
'E': []
}
print(find_all_paths(graph, 'A', 'E'))
# 输出:[['A', 'B', 'D', 'E'], ['A', 'C', 'D', 'E']]
四、总结提升
-
数据结构选择原则:
- 需要快速查找 → 哈希表
- 需要维护顺序 → 链表/队列
- 需要层级关系 → 树结构
- 需要复杂关联 → 图结构
-
算法优化方向:
- 空间换时间(如LRU缓存)
- 使用合适的数据结构加速操作
- 递归与迭代的合理选择
-
调试技巧:
- 对于树/图问题,先手动绘制结构图
- 使用print语句输出中间状态
- 编写单元测试验证边界条件
建议将每个案例手写实现一遍,并通过LeetCode平台(146-LRU缓存、743-网络延迟时间等)进行强化练习。