当前位置: 首页 > news >正文

高级堆结构

一、二项堆(Binomial Heap):理解「合并操作」的优化

二项堆的核心优势是高效合并,类似 “二进制加法”。我们通过「合并两个二项堆」的伪代码和步骤来理解:

核心结构伪代码:
class BinomialTreeNode:def __init__(self, key):self.key = key  # 节点值self.degree = 0  # 度数(子节点数量)self.parent = None  # 父节点self.children = []  # 子节点列表(按度数从小到大排列)class BinomialHeap:def __init__(self):self.trees = []  # 存储二项树(按度数从小到大排序,每个度数最多1棵)self.min_node = None  # 指向最小元素节点
关键操作:合并两个二项堆(类似二进制加法)
def merge_heaps(h1, h2):# 1. 合并两个堆的树列表(按度数从小到大)merged = []i = j = 0while i < len(h1.trees) and j < len(h2.trees):t1 = h1.trees[i]t2 = h2.trees[j]if t1.degree < t2.degree:merged.append(t1)i += 1else:merged.append(t2)j += 1merged.extend(h1.trees[i:])merged.extend(h2.trees[j:])# 2. 合并相同度数的树(类似二进制进位)result = BinomialHeap()carry = None  # 用于暂存合并后的树for tree in merged:if carry is None:carry = treeelse:if carry.degree == tree.degree:# 合并两棵同度数的树(小根作为父节点)if carry.key > tree.key:carry, tree = tree, carry  # 保证carry是小根tree.parent = carrycarry.children.append(tree)carry.degree += 1  # 度数+1else:# 度数不同,直接加入结果result.trees.append(carry)carry = treeif carry is not None:result.trees.append(carry)# 3. 更新最小节点result.update_min()return result
步骤拆解(合并示例):

假设 h1 有一棵树 B2(度数 2),h2 有一棵树 B2(度数 2):

  1. 合并树列表后,得到两个度数为 2 的树。
  2. 合并这两棵树:较小根节点作为父,另一棵作为子,得到一棵 B3(度数 3)。
  3. 最终结果堆只包含 B3,完成合并。

核心理解:二项堆的合并像 “二进制加法”,同度数树合并后度数 + 1,效率远高于二叉堆的 O (n) 合并。

二、斐波那契堆(Fibonacci Heap):理解「延迟操作」

斐波那契堆的高效源于 “不立即处理冲突,延迟到必要时”。以「插入」和「提取最小」为例:

核心结构伪代码:
class FibonacciNode:def __init__(self, key):self.key = keyself.parent = Noneself.children = []  # 子节点列表self.degree = 0  # 子节点数量self.marked = False  # 标记:是否失去过子节点class FibonacciHeap:def __init__(self):self.root_list = []  # 根节点列表(所有树的根)self.min_node = None  # 最小节点指针self.node_count = 0  # 总节点数
1. 插入操作(O (1),体现延迟思想):
def insert(self, key):new_node = FibonacciNode(key)self.root_list.append(new_node)  # 直接加入根列表,不合并# 更新最小节点if self.min_node is None or new_node.key < self.min_node.key:self.min_node = new_nodeself.node_count += 1

步骤理解:插入时直接把新节点作为一棵新树加入根列表,不处理任何合并,所以是 O (1)。

2. 提取最小节点(触发延迟处理,摊还 O (log n)):
def extract_min(self):if self.min_node is None:return None# 1. 把最小节点的子节点加入根列表(失去父节点)for child in self.min_node.children:self.root_list.append(child)child.parent = None# 2. 从根列表移除最小节点self.root_list.remove(self.min_node)self.node_count -= 1# 3. 延迟处理:合并相同度数的树(此时才清理结构)self.consolidate()  # 核心:合并根列表中同度数的树# 4. 重新找最小节点self.min_node = self.find_min_in_root_list()return self.min_node.key

步骤理解:只有提取最小节点时,才会合并根列表中同度数的树(类似二项堆的合并),这个操作的代价被 “摊还” 到之前的插入操作上,所以整体摊还复杂度是 O (log n)。

核心理解:斐波那契堆通过 “延迟合并” 把复杂操作推迟,让简单操作(插入、合并)变得极快。

三、配对堆(Pairing Heap):理解「简单高效的合并」

配对堆的核心是极简的结构两两合并策略,实现简单却高效。

核心结构伪代码:
class PairingNode:def __init__(self, key):self.key = keyself.children = []  # 子节点列表(子堆)class PairingHeap:def __init__(self, key=None):self.root = PairingNode(key) if key is not None else None
1. 合并操作(O (1),体现简单性):
def merge(h1, h2):# 比较两个根,小根作为父节点,大根作为子节点if h1 is None:return h2if h2 is None:return h1if h1.root.key > h2.root.key:h1, h2 = h2, h1  # 保证h1根更小# 把h2作为h1的子节点h1.root.children.append(h2.root)return h1

步骤理解:合并两个配对堆时,只需把根更大的堆作为子节点挂到根更小的堆上,一步完成,所以是 O (1)。

2. 提取最小节点(用 “配对法” 合并子堆):
def extract_min(self):if self.root is None:return Nonemin_key = self.root.key# 合并所有子节点(核心:配对法)if self.root.children:self.root = self.pairwise_merge(self.root.children)else:self.root = Nonereturn min_keydef pairwise_merge(children):# 第一步:两两合并子节点if len(children) == 0:return Noneif len(children) == 1:return children[0]# 两两合并,递归处理剩余merged = []for i in range(0, len(children)-1, 2):merged_child = merge(children[i], children[i+1])merged.append(merged_child)# 若有奇数个,最后一个单独处理if len(children) % 2 == 1:merged.append(children[-1])# 第二步:依次合并结果return pairwise_merge(merged)

步骤理解:提取最小节点(根节点)后,将其子节点两两合并,再递归合并结果,确保合并效率。这种 “配对合并” 策略让摊还复杂度接近 O (log n)。

核心理解:配对堆用最简单的结构(单根 + 子堆列表)和合并策略,在实践中比理论更高效,适合工程实现。

总结:通过核心操作理解高级堆

堆类型最能体现特性的操作操作逻辑核心为什么高效?
二项堆合并按度数从小到大合并,同度数树合并为更高一度树(类似二进制加法)合并复杂度从 O (n) 降为 O (log n)
斐波那契堆插入直接加入根列表,不合并(延迟处理)简单操作 O (1),复杂操作摊还处理
配对堆合并小根作为父,大根作为子,提取时两两合并子堆结构极简,合并逻辑简单,常数小

对于初学者,不需要死记代码,重点理解:

  • 二项堆是 “有序合并的基础”;
  • 斐波那契堆是 “延迟优化的极致”;
  • 配对堆是 “简单实用的优选”。

它们的设计思想(如延迟操作、结构化合并)对理解更复杂的算法非常有帮助。

http://www.lryc.cn/news/623637.html

相关文章:

  • 机器人经验学习1 杂记
  • Ansible 管理变量和事实
  • CW32L011_电机驱动器开发板试用
  • SpringCloud 06 服务容错 Sentinel
  • 云智智慧停充一体云-allnew全新体验-路内停车源码+路外停车源码+充电桩源码解决方案
  • 中国星网发展情况全面分析
  • python实现梅尔频率倒谱系数(MFCC) 除了傅里叶变换和离散余弦变换
  • 3.逻辑回归:从分类到正则化
  • pyecharts可视化图表组合组件_Grid:打造专业数据仪表盘
  • 数据赋能(396)——大数据——抽象原则
  • tauri2项目WindowConfig配置中titleBarStyle样式区别,仅macOS有效
  • 【Jenkins】01 - Jenkins安装
  • 阶段二:7-上网行为安全概述
  • Kotlin集合概述
  • 《PEFLL: Personalized Federated Learning by Learning to Learn》——论文阅读
  • 【Android】Activity创建、显式和隐式跳转、清单文件声明
  • Android 对话框 - 基础对话框补充(不同的上下文创建 AlertDialog、AlertDialog 的三个按钮)
  • 飞算JavaAI结合Redis实现高性能存储:从数据瓶颈到极速读写的实战之旅
  • 关于虾的智能养殖系统的开发与实现(LW+源码+讲解+部署)
  • 数据结构(排序篇)——七大排序算法奇幻之旅:从扑克牌到百亿数据的魔法整理术
  • 三维重建-动手学计算机视觉19(完结)
  • SHAP分析!NRBO-Transformer-BiLSTM回归预测SHAP分析,深度学习可解释分析!
  • ReID/OSNet 算法模型量化转换实践
  • 牛客周赛 Round 105
  • Redis-plus-plus API使用指南:通用操作与数据类型接口介绍
  • EDMA(增强型直接内存访问)技术
  • [每周一更]-(第155期):Go 1.25 发布:新特性、技术思考与 Go vs Rust 竞争格局分析
  • 多线程—飞机大战(加入排行榜功能版本)
  • 亚马逊拉美市场爆发:跨境卖家的本土化增长方程式
  • UE5多人MOBA+GAS 48、制作闪现技能