高级堆结构

一、二项堆(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.pswp.cn/bicheng/93660.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系统学习算法 专题十七 栈

题目一&#xff1a;算法思路&#xff1a;一开始还是暴力解法&#xff0c;即遍历字符串&#xff0c;如果出现当前位置的字符等于后面的字符&#xff0c;则删除这两个字符&#xff0c;然后再从头遍历&#xff0c;如此循环即可但是这样时间复杂度很高&#xff0c;每删除一次就从头…

深入解析函数指针及其数组、typedef关键字应用技巧

目录 一、函数指针变量的创建 1、什么是函数指针变量&#xff1f; 2、函数是否有地址&#xff1f; 3、创建函数指针变量 4、函数指针类型解析 二、函数指针变量的使用 三、两段有趣的代码 1、解释 (*(void (*)())0)(); 2、解释 void (*signal(int, void(*)(int)))(int…

k8s集群搭建一主多从的jenkins集群

方案 --------------------- | Jenkins Master | | - 持久化配置 |<---(hostpath 存储) | - 自动容灾 | --------------------|| Jenkins JNLP 通信| ----------v---------- ------------------- | Jenkins Agent | | Kubernetes Pl…

重温k8s基础概念知识系列三(工作负载)

文章目录1、工作负载简述2、Deployment1.1、创建 Deployment1.2、检查 Deployment上线状态3、StatefulSet4、DaemonSet3.1、创建 DaemonSet3.2、运行DaemonSet5、Job5.1、运行示例 Job5.2、检查 Job 的状态6、CronJob上一节&#xff0c;我们复习了Pod相关知识&#xff0c;大多情…

开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

Go语言并发编程 ------ 锁机制详解

Go语言提供了丰富的同步原语来处理并发编程中的共享资源访问问题。其中最基础也最常用的就是互斥锁&#xff08;Mutex&#xff09;和读写锁&#xff08;RWMutex&#xff09;。1. sync.Mutex&#xff08;互斥锁&#xff09;Mutex核心特性互斥性/排他性&#xff1a;同一时刻只有一…

8月17日星期天今日早报简报微语报早读

8月17日星期天&#xff0c;农历闰六月廿四&#xff0c;早报#微语早读。1、《南京照相馆》领跑&#xff0c;2025年暑期档电影总票房破95亿&#xff1b;2、神舟二十号圆满完成第三次出舱任务&#xff1b;3、宇树G1人形机器人100米障碍赛再夺金牌&#xff1b;4、广东佛山新增报告基…

在QML中使用Chart组件

目录前言1. 如何安装 Chart 组件2. 创建 QML 工程时的常见问题3. 解决方案&#xff1a;改用 QApplication QQuickView修改主函数&#xff08;main.cpp&#xff09;4. QApplication 与 QGuiApplication 的差异为什么 Qt Charts 需要 QApplication&#xff1f;总结示例下载前言 …

【P40 6-3】OpenCV Python——图像融合(两张相同属性的图片按比例叠加),addWeighted()

P40 6-3 文章目录import cv2 import numpy as npback cv2.imread(./back.jpeg) smallcat cv2.imread(./smallcat1.jpeg)#只有两张图的属性是一样的才可以进行溶合 print(back.shape) print(smallcat.shape)result cv2.addWeighted(smallcat, 0.7, back, 0.3, 0) cv2.imshow(…

传输层协议 TCP(1)

传输层协议 TCP&#xff08;1&#xff09; TCP 协议 TCP 全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制; TCP 协议段格式 • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去; • 32 位序号/32 位确认号: 后面详…

黎阳之光:以动态感知与 AI 深度赋能,引领电力智慧化转型新革命

当全球能源结构加速向清洁低碳转型&#xff0c;新型电力系统建设成为国家战略核心&#xff0c;电力行业正经历从传统运维向智慧化管理的深刻变革。2024 年《加快构建新型电力系统行动方案》明确提出&#xff0c;到 2027 年需建成全国智慧调度体系&#xff0c;实现新能源消纳率突…

自动驾驶中的传感器技术34——Lidar(9)

补盲lidar设计&#xff1a;机械式和半固态这里不再讨论&#xff0c;这里主要针对全固态补盲Lidar进行讨论1、系统架构设计采用Flash方案&#xff0c; 设计目标10m10%&#xff0c;实现30m距离的点云覆盖&#xff0c;同时可以验证不同FOV镜头的设计下&#xff0c;组合为多款产品。…

Originality AI:原创度和AI内容检测工具

本文转载自&#xff1a;Originality AI&#xff1a;原创度和AI内容检测工具 - Hello123工具导航 ** 一、AI 内容诚信管理专家 Originality AI 是面向内容创作者的全栈式质量检测平台&#xff0c;整合 AI 内容识别、抄袭查验、事实核查与可读性分析四大核心功能&#xff0c;为…

OpenCV图像平滑处理方法详解

引言 在数字图像处理中&#xff0c;图像平滑是一项基础而重要的预处理技术。它主要用于消除图像中的噪声、减少细节层次&#xff0c;为后续的图像分析&#xff08;如边缘检测、目标识别等&#xff09;创造更好的条件。OpenCV作为最流行的计算机视觉库之一&#xff0c;提供了多种…

每天两道算法题:DAY1

题目一&#xff1a;金币 题目一&#xff1a;金币 1.题目来源&#xff1a; NOIP2015 普及组 T1&#xff0c;难度红色&#xff0c;入门签到题。 2.题目描述&#xff1a; 3.题目解析&#xff1a; 问题转化&#xff1a;求下面的一个数组的前 k 项和。 4.算法原理&#xff1a; …

C++核心语言元素与构建块全解析:从语法规范到高效设计

&#x1f4cc; 为什么需要双维度学习C&#xff1f;核心语言元素 → 掌握标准语法规则&#xff08;避免未定义行为Undefined behavior&#xff09;构建块&#xff08;Building Blocks&#xff09; → 像搭积木一样组合功能&#xff08;提升工程能力&#xff09; 例如&#xff1a…

RK3588开发板Ubuntu系统烧录

Ubuntu22.04——YOLOv8模型训练到RK3588设备部署和推理 文章中给出了通过ARM设备上面的NPU进行深度学习的模型推理过程,在此之前,我们在收到一块全新的rk3588开发板后,需要对其进行系统的烧录,这里以Ubuntu22.04系统为例。 目录 1.获取待烧录系统的镜像 2.烧录工具准备 2.1…

AI评测的科学之道:当Benchmark遇上统计学

AI评测的科学之道&#xff1a;当Benchmark遇上统计学 —— 如何客观评估大模型能力&#xff0c;避免落入数据陷阱 在人工智能尤其是大语言模型&#xff08;LLU&#xff09;爆发式发展的今天&#xff0c;各类模型榜单&#xff08;如Open LLM Leaderboard、LMSys Arena&#xff0…

CSS 基础入门教程:从零开始学习样式表

一、CSS 简介CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于描述 HTML 或 XML 等文档呈现方式的语言。它是现代网页设计的三大核心技术之一&#xff0c;与HTML&#xff08;结构层&#xff09;和JavaScript&#xff08;行为层&#xff09;…

图解简单选择排序C语言实现

1 简单选择排序 简单选择排序&#xff08;Simple Selection Sort&#xff09;是一种基础且直观的排序算法&#xff0c;其核心思想是通过重复选择未排序部分中的最小&#xff08;或最大&#xff09;元素&#xff0c;并将其放到已排序部分的末尾&#xff0c;逐步完成整个序列的排…