Python 高级数据结构

Python 高级数据结构详解

文件信息

  • 文件名: 04_高级数据结构.py
  • 开发思路和开发过程 :
    1. 首先介绍堆(Heap)及其应用
    2. 然后演示优先队列的实现
    3. 接着展示并查集(Disjoint Set)数据结构
    4. 最后介绍Trie树(前缀树)
  • 代码功能: 演示高级数据结构的实现和使用,包括堆、优先队列、并查集和Trie树。

代码实现

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=== 高级数据结构详解结束 ===")

堆操作流程

复制代码
堆操作
├── 插入元素
│   ├── 添加到末尾
│   └── 向上调整
├── 删除最小元素
│   ├── 取出根节点
│   ├── 将末尾元素移到根节点
│   └── 向下调整
├── 查看最小元素
│   └── 直接访问根节点
└── 堆化操作
    ├── 将列表转换为堆
    └── 从最后一个非叶子节点开始向下调整

并查集操作

复制代码
并查集操作
├── 初始化
│   ├── 每个元素父节点指向自己
│   └── 秩初始化为0
├── 查找
│   ├── 查找根节点
│   └── 路径压缩优化
├── 合并
│   ├── 查找两个元素的根节点
│   └── 按秩合并优化
└── 连通性检查
    ├── 查找两个元素的根节点
    └── 比较根节点是否相同

Trie树结构

复制代码
Trie树
├── root节点
│   ├── a
│   │   └── p
│   │       └── p
│   │           ├── l
│   │           │   └── e (is_end_of_word=true)
│   │           └── (is_end_of_word=true)
│   └── b
│       └── a
│           └── n
│               └── a
│                   └── n
│                       └── a (is_end_of_word=true)
相关推荐
晓晓hh8 小时前
JavaSE学习——迭代器
java·开发语言·学习
iFlyCai8 小时前
C语言中的指针
c语言·数据结构·算法
Laurence8 小时前
C++ 引入第三方库(一):直接引入源文件
开发语言·c++·第三方库·添加·添加库·添加包·源文件
查古穆8 小时前
栈-有效的括号
java·数据结构·算法
汀、人工智能8 小时前
16 - 高级特性
数据结构·算法·数据库架构·图论·16 - 高级特性
kyriewen118 小时前
你点的“刷新”是假刷新?前端路由的瞒天过海术
开发语言·前端·javascript·ecmascript·html5
014-code8 小时前
String.intern() 到底干了什么
java·开发语言·面试
421!9 小时前
GPIO工作原理以及核心
开发语言·单片机·嵌入式硬件·学习
极梦网络无忧9 小时前
OpenClaw 基础使用说明(中文版)
python
codeJinger9 小时前
【Python】操作Excel文件
python·excel