斐波那契堆

斐波那契堆——怎么发明一种非常聪明的数据结构——学习笔记 斐波那契堆从0开始,一步一步实现该数据结构,Java实现 阅读详情

总结:这一章讲了斐波那契堆,它是一种比二项堆更松散的堆,它由一组无序的二项树组成,对不涉及删除元素的操作,它仅需O(1)的平摊运行时间。本章介绍斐波那契堆的插入、合并、删除等操作。

 

1.    斐波那契堆的结构

每个结点x的域:

1)  父节点p[x]

2)  指向任一子女的指针child[x]

3)  左兄弟left[x]

4)  右兄弟right[x]

5)  子女的个数degree[x]

6)  布尔值域mark[x]

 

在斐波那契堆中,结点x的子女被链接成一个环形双链表,称为x的子女表。当left[x]=right[x]=x时,说明x是独子。

 

mark域记录了每个结点的一小段历史:

1)  在某个时刻,x是个根

2)  然后,x被链接到另一个结点上(CONSOLIDATE (FIB-HEAP-LINK) )

3)  再通过切断来去除x的两个子女(CUT, CASCADING-CUT)

一旦第二个孩子失掉了,x与其父节点之间的联系就被切断了,x成为一个新根。如果发生了第1步和第2步,且x的一个孩子被切割掉了,则mark[x]为TRUE。

 

在一个斐波那契堆中,所有树的根都通过用其left和right指针链接成一个环形的双链表,称为该堆的根表。min[H]指向根表中具有最小关键字的结点。n[H]代表H中目前包含的结点个数。

 

势函数:Φ(H) = t(H) + 2m(H),其中t(H)为根表中树的棵树,m(H)为H中有标记的结点的个数。

 

最大度数:结点最大度数的上界D(n)=O(lgn)

 

2.    可合并堆的操作

1)创建

MAKE-FIB-HEAP,分配并返回一个斐波那契堆对象H,且n[H]=0, min[H]=NIL。

实际代价:O(1)

势:Φ(H)=0

平摊代价:O(1)

 

2)插入

插入操作直接将结点插入根表中。

实际代价:O(1)

势的增加:(t(H)+1+2m(H))-(t(H)+2m(H))=1

平摊代价:O(1)+1=O(1)

 

伪代码

FIB-HEAP-INSERT(H,x)

degree[x] <- 0

p[x] <- NIL

child[x] <- NIL

left[x] <- x

right[x] <- x

mark[x] <- FALSE

concatenate the root list containing x with root list H

if min[H]=NIL or key[min[H]] > key[x]

      then min[H] <- x

n[H] <- n[H]+1

 

3)寻找最小结点

min[H]指向最小结点

实际代价:O(1)

势的增加:0

平摊代价:O(1)

 

4)合并

直接将两个堆的根表并置,并确定新的min[H]

实际代价:O(1)

势的增加:0

平摊代价:O(1)

 

伪代码

FIB-HEAP-UNION(H1,H2)

H <- MAKE-FIB-HEAP()

min[H] <- min[H1]

concatenate the root list of H2 with the root list of H

if(min[H]=NIL or key[min[H1]]>key[min[H2]])

      then min[H] <- min[H2]

n[H] <- n[H1]+n[H2]

free the objects H1 and H2

return H

 

5)抽取最小结点

先将最小结点的每个子女都成为一个根,然后将度数相同的根链接起来。注意,直到这里,才真正完成了根表中的树的合并。

实际代价:O(D(n)+t(H))

势的增加:至多(D(n)+1+2m(H))-(t(H)+2m(H))=D(n)-t(H)+1

平摊代价:O(D(n))=O(lgn)

 

伪代码

FIB-HEAP-EXTRACT-MIN(H)

z <- min[H]

if z!=NIL

      then for each child x of z

do add x to the root list of H

                    p[x] <- NIL

            remove z from the root list of H

            if z=right[z]

                 then min[H] <- NIL

                 else min[H] <- right[z]

                       CONSOLIDATE(H)

            n[H] <- n[H]-1

return z

 

CONSOLIDATE(H)将H根表中的度数相同的结点链接起来,直到根表中每个度数至多只有一个根。用到辅助数组A[0…D(n[H])],A[i]=y代表degree[y]=i

伪代码

CONSOLIDATE(H)

for i <- 0 to D(n[H])

      do A[i] <- NIL

for each node w in the root list of H

      do x <- w

         d <- degree[x]

         while A[d]!=NIL

                 do y <- A[d]

                    if key[y]<key[x]

                            then exchange y <-> x

                    FIB-HEAP-LINK(H,y,x)

                    A[d] <- NIL

                    d <- d+1

         A[d] <- x

min[H] <- NIL

for i <- 0 to D(n[H])

      do if A[i]!=NIL

                 then add A[i] to the root list of H

if min[H]=NIL or key[A[i]]<key[min[H]]

                              then min[H] <- A[i]

 

伪代码

FIB-HEAP-LINK(H,y,x)

remove y from the root list of H

make y a child of x, incrementing degree[x]

mark[y] <- FALSE

 

6)减小一个关键字

若结点的关键字减小后,关键字小于其父节点的关键字,则将此结点移出,置入根表中,另外,还需执行级联切断操作。

 

伪代码

FIB-HEAP-DECREASE-KEY(H,x,k)

if k > key[x]

      then error “error”

key[x] <- k

y <- p[x]

if y!=NIL and key[x]<key[y]

      then CUT(H,x,y)

            CASCADING-CUT(H,y)

if key[x]<key[min[H]]

      then min[H] <- x

 

伪代码

CUT(H,x,y)

remove x from the child list of y, decrementing degree[y]

add x to the root list of H

p[x] <- NIL

mark[x] <- FALSE

 

由于CUT使切断的结点的父节点y又失去了一个孩子,因此CASCADING-CUT判断父节点的MARK,若为FALSE,则由于y失去了一个孩子,设mark[y]为TRUE,若mark[y]已经为TRUE了,那么y已经失去了两个孩子了,那么继续切断y与p[y],再接着判断p[y]的MARK,一直沿树递归上去,直到找到一个根节点或未加标记的结点。

 

伪代码

CASCADING(H,y)

z <- p[y]

if z!=NIL

      then if mark[y]=FALSE

                 then mark[y]=TRUE

                 else CUT(H,y,z)

                       CASCADING-CUT(H,z)

 

复杂度分析:

设递归调用了c次CASCADING()

实际代价:O(c)

势的变化:至多(t(H)+c+2(m(H)-c+2))-(t(H)+2m(H))=4-c (c-1个结点被级联切断消除标记,最后一次CASCADING-CUT可能给某个结点加上标记)

平摊代价:O(c)+4-c=O(1)

 

7)删除

平摊代价:O(lgn)

 

伪代码

FIB-HEAP-DELETE(H,x)

FIB-HEAP-DECREASE-KEY(H,x,-INF)

FIB-HEAP-EXTRACT-MIN(H)

Dijkstra迪杰斯特拉算法 最短路径 Fibonacci Heap斐波那契堆实现以及与链表速度对比 比较懒,斐波那契堆只写了删除最小值和降低节点的值,但是也是最复杂的两个操作啦! In this assignment, there are three main parts in my code including the random directed graph generator, the dijkstra algorithm with list, and the dijkstra algorithm with Fibonacci Heap. The number of the node V is f 阅读详情

相关推荐

二项堆与斐波那契堆

二项堆 二项堆是符合最小堆性质的二项树链接成的森林二项树是形如下图的树

小虎 的博客 2097

斐波那契堆(Fibonacci heap)原理详解(附java代码实现)

前言   斐波那契堆(Fibonacci heap)是计算机科学中最小堆有序树的集合。它和二项式堆有类似的性质,但比二项式堆有更好的均摊时间。堆的名字来源于斐波那契数,它常用于分析运行时间。 堆结构介绍   基本术语介绍:   关键字:堆节点储存的用于比较的信息   度数:堆节点拥有的孩子数(注意,不包括孩子的孩子)   左兄弟:节点左边的兄弟节点 ...

weixin_30399871的博客 730

斐波那契堆(Fibonacci heaps)

canh

solar一抹阳光的专栏 6145

斐波那契堆(Fibonacci Heap)

也许我们每个人都知道斐波那契数列(Fibonacci sequence)。即这样一个数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144...,如果我们用伪代码比表示: int FibonacciSequence(int n){ if (n == 1 || n == 2) { return 1; } return

yzf0011的专栏 4179

算法导论之斐波那契堆

斐波那契堆,和二项堆类似,也是由一组最小堆有序的树构成。注意区别,不是二项树,是有根而无序的树。导论中,斐波那契堆只是具有理论上的意义,是以平摊分析为指导思想来设计的数据结构,主要是渐进时间界比二项堆有改善。斐波那契堆除去删除元素操作外,其他操作只有O(1)的平摊运行时间,而二项堆需要O(lgn)的最坏情况运行时间。但若要斐波那契堆能转化为实际应用,除要保证有相同平摊时间界限外,还需更简单的数据结

医疗影像检索 4404

[Python] 斐波那契堆的实现

[Python] 斐波那契堆的实现斐波那契堆是一种基于堆的数据结构,其用途主要为: - 实现“可合并堆” -某些在斐波那契堆中常数摊还时间内完成的操作频繁使用的应用具体函数(操作):首先介绍堆中元素(节点)的实现: 元素初始化def __init__(self, key): self.key=key #关键字 self.degree=0 #元素在堆中的度

倒霉茄子的博客 1891

斐波那契堆的C++实现

本文改编自《算法导论》第三版第19章:斐波那契堆。

Castria的博客 3056

S32K144 ADC硬件触发实战:PDB模块配置与DMA传输全流程解析

本文详细解析了S32K144微控制器中ADC硬件触发的全流程实现。通过配置PDB模块产生精确的定时触发信号,并联动DMA实现转换数据的自动搬运,构建了一个无需CPU干预的高效、低抖动数据采集系统。文章深入讲解了时钟配置、模块初始化、DMA引擎搭建及实战调试技巧,为汽车电子和工业控制应用提供了可靠的解决方案。

weixin_29174141的博客 225

浅谈斐波那契堆

斐波那契堆是一种优先队列数据结构,具有较好的平摊时间复杂度,特别是在合并堆和减少键操作上表现优异。斐波那契堆的结构特点。它由一组最小堆有序的树组成,每棵树都是符合最小堆性质的,但不像二项堆那样严格的结构。每个节点有父指针、孩子链表,以及左右兄弟指针,这样形成一个环形双向链表。节点还需要记录度数、标记(mark)等属性。标记用于在删除节点时判断是否需要级联剪切,以保持结构的平衡。接下来,我们从数据结构、操作原理来大概讲一下。

eso1983的博客 1021

AES128加密算法开发(含源码)

本文详解了AES128加密算法的原理与C语言实现。AES128是当前广泛使用的对称加密标准,采用128位密钥和10轮变换,具有高安全性和高效性。文章从算法背景、核心概念(混淆与扩散)入手,详细解析了4×4状态矩阵表示、4个核心变换(字节替换、行移位、列混合、轮密钥加)以及密钥扩展过程。特别针对汽车电子应用场景,如ECU通信加密、车钥匙认证等,说明了AES128在资源受限环境中的优势。通过分步图解和原理剖析,帮助开发者深入理解这一加密标准的技术细节与实现方法。

汽车电子软件开发笔记 2916

Pixhawk变砖自救指南:从DFU模式到固件重刷全流程(附2.4.8实测)

本文详细介绍了Pixhawk飞控变砖后的自救方法,从DFU模式进入、固件重刷到高级恢复技巧全流程。特别针对国产版本boot0引脚未引出的特殊情况提供了解决方案,帮助用户通过QGC或Mission Planner地面站工具恢复飞控功能,适用于2.4.8等常见固件版本。

weixin_29168813的博客 337

斐波那契堆为何称为斐波那契

本文只讨论斐波那契堆与斐波那契数列的关系,不对其增删改查做说明。(只是讨论) 废话一句: 斐波那契数列的递推公式:an=an-1+an-2 废话两句: 剪枝操作: 一个节点不能丢掉两个子节点,不然他也会被掉 树的合并: 两个同度数的树合并,取其中key值更小的根做为新树的根节点,偏大的根作为偏小的根的子节点 正文: 斐波那契堆由多个斐波那契树组成,符合斐波那契数列递推公式的是斐波那契树的最小节点数。记y阶斐波那契树为yd,其节点数为Nd,则有: Nd >= Nd...

qq_33956242的博客 417

PPT里文字太多如何排版-一口气教你7种布局瞬间让PPT高大上起来

PPT里全是文字且很拥挤怎么办?本篇教你使用7种不同的排版让你的PPT瞬间变得高大上起来。

打造全国最全的AI Agent开发知识领域的博客 5022

算法导论笔记:19斐波那契堆

可合并堆是支持以下5种操作的数据结构,其中每个元素都有一个关键字:        MAKE-HEAP():创建和返回一个新的不含任何元素的堆。        INSERT(H, x):将一个已填入关键字的元素x插入堆H中。        MINIMUM(H):返回一个指向堆H中具有最小关键字元素的指针。        EXTRACT-MIN(H):从堆H中删除最小关键字的元素,并返回指向该

程序员的自我修养 6274

ansys license许可证问题:Ansys License Manager Release 2024 R1...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 5367

光伏硅片瑕疵检测边缘计算方案:Java+YOLOv11n+GraalVM Native Image+树莓派5部署,工业级高可靠落地

本文提出了一种基于边缘计算的光伏硅片瑕疵检测方案,针对传统人工检测和云端AI方案的不足,采用Java+YOLOv11n+树莓派5的技术路线,实现了低延迟、高可靠的工业级检测。方案核心特点包括: 分层解耦的边缘架构,将感知、推理全链路下沉到树莓派5,端到端延迟<100ms; 创新性技术选型组合:Java 17+ONNX Runtime+GraalVM Native Image,内存占用<200MB; 安防级可靠性设计,支持断网缓存、看门狗守护、异常自动恢复等工业场景需求; 完全基于开源技术栈,硬件

2601_94871597的博客 474
上一篇: virtualbox下安装ubuntu8.04 关于 虚拟文件的设置
HappyCoffeeYsu
博客等级 码龄15年 0粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值