python
复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文件名: 04_高级数据结构.py
开发思路和开发过程:
1. 首先介绍堆(Heap)及其应用
2. 然后演示优先队列的实现
3. 接着展示并查集(Disjoint Set)数据结构
4. 最后介绍Trie树(前缀树)
代码功能: 演示高级数据结构的实现和使用,包括堆、优先队列、并查集和Trie树。
"""
print("=== 高级数据结构详解 ===\n")
# 1. 堆(Heap)
print("1. 堆(Heap):")
import heapq
# Python使用heapq模块实现最小堆
print("1.1 最小堆:")
min_heap = []
# 向堆中添加元素
heapq.heappush(min_heap, 3)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 4)
heapq.heappush(min_heap, 2)
print(f"向堆中添加元素后: {min_heap}")
# 弹出最小元素
min_element = heapq.heappop(min_heap)
print(f"弹出最小元素: {min_element}")
print(f"弹出后堆的内容: {min_heap}")
# 查看最小元素但不弹出
smallest = min_heap[0]
print(f"当前最小元素: {smallest}")
# 将列表转换为堆
numbers = [5, 2, 8, 1, 9]
heapq.heapify(numbers)
print(f"将列表转换为堆: {numbers}")
# 获取最大的3个元素
largest_three = heapq.nlargest(3, numbers)
print(f"最大的3个元素: {largest_three}")
# 获取最小的3个元素
smallest_three = heapq.nsmallest(3, numbers)
print(f"最小的3个元素: {smallest_three}")
# 1.2 最大堆的实现(通过负数模拟)
print("\n1.2 最大堆(通过负数模拟):")
max_heap = []
# 添加元素(取负数)
heapq.heappush(max_heap, -3)
heapq.heappush(max_heap, -1)
heapq.heappush(max_heap, -4)
heapq.heappush(max_heap, -2)
print(f"向最大堆中添加元素后: {[-x for x in max_heap]}")
# 弹出最大元素(取负数)
max_element = -heapq.heappop(max_heap)
print(f"弹出最大元素: {max_element}")
print(f"弹出后堆的内容: {[-x for x in max_heap]}")
print()
# 2. 优先队列(Priority Queue)
print("2. 优先队列(Priority Queue):")
import queue
# 使用queue.PriorityQueue
pq = queue.PriorityQueue()
# 添加元素(优先级,值)
pq.put((2, "中等优先级任务"))
pq.put((1, "高优先级任务"))
pq.put((3, "低优先级任务"))
pq.put((1, "另一个高优先级任务"))
print("添加任务到优先队列:")
print(" (1, '高优先级任务')")
print(" (2, '中等优先级任务')")
print(" (3, '低优先级任务')")
print(" (1, '另一个高优先级任务')")
# 处理任务(按优先级顺序)
print("\n按优先级处理任务:")
while not pq.empty():
priority, task = pq.get()
print(f" 处理优先级 {priority} 的任务: {task}")
# 使用heapq实现自定义优先队列
class CustomPriorityQueue:
"""自定义优先队列"""
def __init__(self):
self._queue = []
self._index = 0 # 用于处理优先级相同的情况
def push(self, item, priority):
"""添加元素"""
heapq.heappush(self._queue, (priority, self._index, item))
self._index += 1
def pop(self):
"""弹出元素"""
if self._queue:
return heapq.heappop(self._queue)[-1] # 返回item部分
raise IndexError("优先队列为空")
def is_empty(self):
"""判断是否为空"""
return len(self._queue) == 0
# 使用自定义优先队列
custom_pq = CustomPriorityQueue()
custom_pq.push("任务A", 3)
custom_pq.push("任务B", 1)
custom_pq.push("任务C", 2)
custom_pq.push("任务D", 1)
print("\n使用自定义优先队列:")
while not custom_pq.is_empty():
task = custom_pq.pop()
print(f" 处理任务: {task}")
print()
# 3. 并查集(Disjoint Set)
print("3. 并查集(Disjoint Set):")
class DisjointSet:
"""并查集实现"""
def __init__(self, n):
self.parent = list(range(n)) # 初始化,每个元素的父节点是自己
self.rank = [0] * n # 秩(用于优化)
def find(self, x):
"""查找元素的根节点(带路径压缩优化)"""
if self.parent[x] != x:
# 路径压缩:将路径上的所有节点直接连接到根节点
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
"""合并两个集合(按秩合并优化)"""
root_x = self.find(x)
root_y = self.find(y)
if root_x != root_y:
# 按秩合并:将秩小的树连接到秩大的树下
if self.rank[root_x] < self.rank[root_y]:
self.parent[root_x] = root_y
elif self.rank[root_x] > self.rank[root_y]:
self.parent[root_y] = root_x
else:
self.parent[root_y] = root_x
self.rank[root_x] += 1
def connected(self, x, y):
"""判断两个元素是否属于同一集合"""
return self.find(x) == self.find(y)
# 使用并查集解决图的连通性问题
print("使用并查集判断图的连通性:")
# 假设有6个节点(0-5)
dsu = DisjointSet(6)
# 添加边 (连接节点)
edges = [(0, 1), (1, 2), (3, 4)]
print(f"添加边: {edges}")
for u, v in edges:
dsu.union(u, v)
# 查询连通性
queries = [(0, 2), (1, 3), (3, 4)]
print("查询节点连通性:")
for u, v in queries:
connected = dsu.connected(u, v)
print(f" 节点 {u} 和 {v} 是否连通: {connected}")
print()
# 4. Trie树(前缀树)
print("4. Trie树(前缀树):")
class TrieNode:
"""Trie树节点"""
def __init__(self):
self.children = {} # 子节点
self.is_end_of_word = False # 标记是否为单词结尾
class Trie:
"""Trie树实现"""
def __init__(self):
self.root = TrieNode()
def insert(self, word):
"""插入单词"""
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end_of_word = True
def search(self, word):
"""搜索单词"""
node = self.root
for char in word:
if char not in node.children:
return False
node = node.children[char]
return node.is_end_of_word
def starts_with(self, prefix):
"""检查是否存在以给定前缀开头的单词"""
node = self.root
for char in prefix:
if char not in node.children:
return False
node = node.children[char]
return True
def delete(self, word):
"""删除单词"""
def _delete(node, word, index):
if index == len(word):
if not node.is_end_of_word:
return False
node.is_end_of_word = False
return len(node.children) == 0
char = word[index]
if char not in node.children:
return False
should_delete_child = _delete(node.children[char], word, index + 1)
if should_delete_child:
del node.children[char]
return not node.is_end_of_word and len(node.children) == 0
return False
_delete(self.root, word, 0)
# 使用Trie树
print("使用Trie树进行单词操作:")
trie = Trie()
# 插入单词
words = ["apple", "app", "application", "apply", "banana"]
print(f"插入单词: {words}")
for word in words:
trie.insert(word)
# 搜索单词
search_words = ["app", "appl", "banana", "band"]
print("搜索单词:")
for word in search_words:
found = trie.search(word)
print(f" 单词 '{word}' 是否存在: {found}")
# 前缀检查
prefixes = ["ap", "ban", "cat"]
print("前缀检查:")
for prefix in prefixes:
has_prefix = trie.starts_with(prefix)
print(f" 是否存在以 '{prefix}' 开头的单词: {has_prefix}")
# 删除单词
delete_word = "app"
print(f"\n删除单词 '{delete_word}'")
trie.delete(delete_word)
# 再次搜索
print(f"删除后搜索 '{delete_word}': {trie.search(delete_word)}")
print(f"删除后搜索 'apple': {trie.search('apple')}")
print("\n=== 高级数据结构详解结束 ===")