1. 程式人生 > >斐波那契堆(fibonacci heap)基礎

斐波那契堆(fibonacci heap)基礎

斐波那契堆是由一組最小堆有序樹組成,其中的每棵樹都必須符合最小堆屬性。 簡單點,斐波那契堆是由一組有點特別的樹組成。除了兩個與元素刪除有關的 操作(EXTRACT-MIN和DELETE)之外,它的其它操作都能在常數時間內完成。可 以看下斐波那契堆和二叉堆的執行時間對比表:

斐波那契堆的特點:不涉及刪除元素的操作有O(1)的平攤時間。 Extract-Min和Delete的數目和其它相比較小時效率更佳。
用途:稠密圖每次Decrease-key只要O(1)的平攤時間,和二項堆的O(lgn)相比是巨大的改進。
斐波那契堆的結構較二項堆更鬆散。因此對結構的維護可以到方便時再做。
斐波那契堆中的樹是有根而無序的。每個節點包含一個指向其父節點的指標p[x],以及一個指向其任一子女的指標child[x](指向子女雙鏈表)。
每個孩子有left[x]和right[x]。(意義:在O(1)的時間內去掉一個節點,或者在O(1)的時間內合併雙鏈表。)其它域: degree[x]儲存子女個數。 mark[x]指示自從x上一次成為另一節點的子女以來,它是否失掉一個孩子。
一個給定的斐波那契堆可以通過一個指向其含有最小關鍵字樹的指標來訪問。
斐波那契堆的關鍵思想在於儘量延遲對堆的維護。建立一個新的斐波那契堆: MAKE_Fib_Heap有O(1)的代價。
插入一個節點:分三步進行: 1,為新的節點置p,child,left,right,mark等域。時間消耗: O(1)。 2,將包含x的根表和根表H連線。時間消耗: O(1) 。3,在O(1)的時間內調整指向該堆的指標min[x] 時間消耗: O(1) 。以節點數表示勢。勢的增加為1,實際代價為O(1)。所以平攤代價為O(1)。
尋找最小節點: min[x]指向的節點即為最小節點。因為勢沒有變化,所以這個操作的平攤代價為O(1)。
合併兩個斐波那契堆:分為3步: 1。合併根表 2。設定新的min[h] 3。重置n[x]。
抽取最小節點:這是最複雜的工作。被延遲的對根表的調整工作最終由這個操作進行。 1。去掉最小值,將其每個孩子都加入根表。 2。將相同度數樹的合併。
調整根表的步驟 1。在根表中找出兩個具有相同度數的根x和y,且key[x]《key[y] 2。將y與x連線。將y從根表裡去掉,成為x一個孩子,並增加degree[x]。
減小一個節點的權 1。若此減小不影響堆序,不作調整。 2。若影響堆序,則從堆中刪除該節點,將其加入根表。並檢查其父親的mark位。
若為false,則停止,並將其置為true。若為true,則刪除其父親,繼續遞歸向上執行。直到一個
節點mark域為false或該節點為根節點為止。
刪除一個節點: 1。將該節點權調整至最小 2。抽取最小值。
證明最大度數界:證明刪除或extract-min的平攤時間為O(lgn)。引理1:設x為斐波那契堆中任一節點,並假設degree[x]=k。設y1,y2,。。。yk表示按與x連結的次序排列的x的子女,從最早的到最遲的,則對i=2,3,...,k,有degree[y1]>=0且degree[yi]>=i-2 證明:顯然degree[y1]》=0 對i>=2,注意到y1被連結到x上時,y1,y2,。。yi-1都是x的子女,故我們必有degree[x]>=i-1 又僅當degree[x]=degree[yi]時,才將yi連結到x上。故此時必有degree[yi>=i-1,在此之後,節點yi至多失去一個孩子,因為失去兩個就被切斷了。所以degree[yi]>=i-2
引理2:對所有的整數k>=0,Fk+2=1+sum(Fi) [0<=i<=k] ,F為斐波那契數。用數學歸納法證明。並可證明不等式 Fk+2 >= G^k ,其中G為黃金分割率。 (1+5^0.5)/2=1.161803...
引理3:設x為斐波那契堆中任一節點,並設k=degree[x],那麼,size(x)>=Fk+2>=G^k。
推論:在一個包含n個節點的斐波那契堆中節點的最大度數為O(lgn)。

相關推薦

fibonacci heap基礎

斐波那契堆是由一組最小堆有序樹組成,其中的每棵樹都必須符合最小堆屬性。 簡單點,斐波那契堆是由一組有點特別的樹組成。除了兩個與元素刪除有關的 操作(EXTRACT-MIN和DELETE)之外,它的其它操作都能在常數時間內完成。可 以看下斐波那契堆和二叉堆的執行時間對比表: 斐波那契堆的特點:不涉及刪除元素的操

Fibonacci Heap

也許我們每個人都知道斐波那契數列(Fibonacci sequence)。即這樣一個數列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144...,如果我們用虛擬碼比表示: int FibonacciSequence(int n){

java數列Fibonacci sequence的三種方式:遞迴,備忘錄,動態規劃

java斐波那契數列(Fibonacci sequence)的三種方式:遞迴,備忘錄,動態規劃 1.最常使用的是遞迴,就是從上往下尋找答案,然後在返回來。 2.備忘錄也是從上往下,只是去掉了遞迴中重複計算的部分,因為它使用一個容器來裝已經計算出的值,這裡就多一個判斷,如果計算過該式子,就直接

遞迴和遞推演算法求數列Fibonacci數列

一、遞迴演算法 import java.util.Scanner; //Fibonacci數列:1,1,2,3,5,8,... //求該數列第n個數的值。 //數列滿足遞迴公式:F1=1,F2+=1,Fn=Fn-1 + Fn-2 public class Fibonacci { pub

數列Fibonacci sequence,又稱黃金分割數列

斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波納契數列

C語言、Python實現Fibonacci

1、C語言實現   有一對兔子,從出生後第3個月起每個月都生一對兔子。小兔子長到第3個月後每個月又生一對兔子。假設所有兔子都不死,問每個月的兔子總數為多少? #include<stdio.h> int main() { int f1=1,f2=1,f3; int i;

用Python編寫數列Fibonacci Sequence)

斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上

[luoguP2626] 數列升級版模擬

sub std [1] 斐波那契數 == cnblogs () ios git 傳送門 模擬 代碼 #include <cmath> #include <cstdio> #include <iostream>

數列大數加法

斐波那契 ++ add ret div 加法 clas 註意 cin 題意: 求斐波那契的前10000項目 分析: 模擬豎式加法, 用string作為數字的儲存形式 #include<bits/stdc++.h> using namespace std; st

題解 P2626 【數列升級版

實現 ace 升級版 因數 退出 turn 思路 font return 題解 P2626 【斐波那契數列(升級版)】 這一道題目的解法多種多樣,但就對於題目本身而言拿暴力分應該不是太難,簡單地模擬一下斐波拉契的過程,求出第n個,最後分解質因數也不難暴力出奇跡。對於代碼的實

P2626 數列升級版

sam sin use important turn 質數 spa pre stream 題目背景 大家都知道,斐波那契數列是滿足如下性質的一個數列: ? f(1) = 1 ? f(2) = 1 ? f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 為整數

公約數luogu 1306

for ace 輸入輸出格式 () style 數列 reg range algorithm 題目描述 對於Fibonacci數列:1,1,2,3,5,8,13......大家應該很熟悉吧~~~但是現在有一個很“簡單”問題:第n項和第m項的最大公約數是多少? Update:

P2626 數列升級版————素數,數列,分解質因數

題解:本題主要考查素數,斐波那契數列,分解質因數。先求出斐波那契數列的mod,再分解。 程式碼如下: #include<iostream> using namespace std; long int f[51],mod=2147483648,m; int n,i,flag=0

[洛谷]P2626 數列升級版 (#數學 -1.11)

題目描述 請你求出第n個斐波那契數列的數mod(或%)2^31之後的值。並把它分解質因數。 輸入輸出格式 輸入格式: n 輸出格式: 把第n個斐波那契數列的數分解質因數。 輸入輸出樣例

P2626 數列升級版 AC於2018.10.20

原題 題目背景 大家都知道,斐波那契數列是滿足如下性質的一個數列: f(1) = 1f(1)=1 f(2) = 1f(2)=1 f(n)=f(n−1)+f(n−2) (n≥2 且 n 為整數)。 題目描述 請你求出第n個斐波那契數列的數mod(或%)2^{31}之

矩陣快速冪求數列初學整理

  參考文章:          感謝以上兩位大神讓我明白瞭如何用矩陣快速冪求斐波那契數列。   題外話:線代真的要好好學,這學期剛好學線代,初期還是蠻認真的,可是後來就勉強能聽懂,然後慢慢~~。萬惡的線代,上學期去湘潭大學參加中南地區程式設計邀請賽第一題就是一個矩陣,

劍指offer之數列Java實現

斐波那契數列 NowCoder 題目描述: 大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。 n<=39 ###解題思路: 整體思路:考慮負數,大數,演算法的複雜度,空間的浪費 public class

遞迴:數列兔子總數

反覆學習反覆學習。 因為自己對遞迴還是不太熟練,於是做POJ1753的時候就很吃力,就是翻棋子直到棋盤上所有棋子的顏色一樣為止,求最少翻多少次,方法是列舉遞迴。然後就打算先做另一道遞迴的題(從陣列中取

劍指offer面試題10:數列Java 實現

題目:大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項。 思路:使用遞迴會重複計算,效率較低,可以用迴圈自下到上計算。 測試用例: 功能測試:輸入3、5、10 等。 邊界測試:輸入0、1、2 效能測試:輸入較大的數(如40、50、

數列C++類

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 352457