3 FibonacciHeap
3 FibonacciHeap
CS31005: Algorithms-II
Autumn 2020
IIT Kharagpur
Heaps as Priority Queues
You have seen binary min-heaps/max-heaps
Can support creating a heap, insert, finding/extracting
the min (max) efficiently
Can also support decrease-key operations efficiently
However, not good for merging two heaps
O(n) where n is the total no. of elements in the two heaps
Variations of heaps exist that can merge heaps efficiently
May also improve the complexity of the other operations
Ex. Binomial heaps, Fibonacci heaps
We will study Fibonacci heaps, an amortized data
structure
A Comparison
Binary heap Binomial heap Fibonacci heap
Operation
(worst-case) (worst-case) (amortized)
18 52 38 30 26 46
39 41 35
min[H]
23 7 3 17 24
18 52 38 30 26 46
39 41 35
Additional Variables
Each node x also has two other fields
degree[x] – stores the number of children of x
mark[x] – indicates whether x has lost a child since the last
time x was made the child of another node
We will denote marked nodes by color black, and unmarked
ones by color grey
A newly created node is unmarked
A marked node also becomes unmarked whenever it is made
the child of another node
Amortized Analysis
We mentioned Fibonacci heap is an amortized data
structure
We will use the potential method to analyse
Let t(H) = no. of trees in a Fibonacci heap H
Let m(H) = number of marked nodes in H
Potential function used
Φ (H) = t(H) + 2m(H)
Operations
Create an empty Fibonacci heap
Insert an element in a Fibonacci heap
Merge two Fibonacci heaps (Union)
Extract the minimum element from a Fibonacci heap
Decrease the value of an element in a Fibonacci heap
Delete an element from a Fibonacci heap
Creating a Fibonacci Heap
This creates an empty Fibonacci heap
Create an object to store min[H] and n[H]
Initialize min[H] = NIL and n[H] = 0
Potential of the newly created heap Φ (H) = 0
Amortized cost = actual cost = O(1)
Inserting an Element
Add the element to the left of min[H]
Update min[H] if needed
Insert 21
21
min[H]
17 24 23 7 3
30 26 46
18 52 41
35
39 44
Inserting an Element (contd.)
Add the element to the left of node pointed to by min[H]
Update min[H] if needed
min[H]
17 24 23 7 21 3
30 26 46
18 52 41
35
39 44
Amortized Cost of Insert
Actual Cost O(1)
Change in potential +1
One new tree, no new marked node
Amortized cost O(1)
Merging Two Heaps (Union)
Concatenate the root lists of the two Fibonacci heaps
Root lists are circular, doubly linked lists, so can be easily
concatenated
min[H1] min[H2]
23 24 17 7 3 21
30 26 46
18 52 41
35
39 44
Merging Two Heaps (contd.)
Concatenate the root lists of the two Fibonacci heaps
Root lists are circular, doubly linked lists, so can be easily
concatenated
min[H]
23 24 17 7 3 21
30 26 46
18 52 41
35
39 44
Amortized Cost of Merge/Union
Actual cost = O(1)
Change in potential = 0
Amortized cost = O(1)
Extracting the Minimum Element
Step 1:
Delete the node pointed to by min[H]
Concatenate the deleted node’s children into root list
min[H]
7 24 23 17 3
30 26 46 18 52 41
35 39 44
Extracting the Minimum (contd.)
Step 1:
Delete the node pointed to by min[H]
Concatenate the deleted node’s children into root list
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
35
Extracting the Minimum (contd.)
Step 2: Consolidate trees so that no two roots have same
degree
Traverse the roots from min towards right
Find two roots x and y with the same degree, with key[x] ≤
key[y]
Remove y from root list and make y a child of x
Increment degree[x]
Unmark y if marked
We use an array A[0..D(n)] where D(n) is the maximum
degree of any node in the heap with n nodes, initially all
NIL
If A[k] = y at any time, then degree[y] = k
Extracting the Minimum (contd.)
Step 2: Consolidate trees so that no two roots have same
degree. Update min[H] with the new min after
consolidation.
current
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
35
Extracting the Minimum (contd.)
0 1 2 3
A
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
current
35
Extracting the Minimum (contd.)
0 1 2 3
A
min[H]
7 24 23 17 18 52 41
30 26 46 39 44
current
35
Merge 17 and 23 trees
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 24 17 18 52 41
30 26 46 23 39 44
35
Merge 7 and 17 trees
Extracting the Minimum (contd.)
0 1 2 3
A
min[H] current
24 7 18 52 41
26 46 17 30 39 44
35 23
Merge 7 and 24 trees
Extracting the Minimum (contd.)
0 1 2 3
A
min[H] current
7 18 52 41
24 17 30 39 44
26 46 23
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 18 52 41
24 17 30 39 44
26 46 23
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 18 52 41
24 17 30 39 44
26 46 23
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 18 52 41
24 17 30 39 44
26 46 23
Merge 41 and 18 trees
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 52 18
24 17 30 41 39
26 46 23 44
35
Extracting the Minimum (contd.)
0 1 2 3
A
current
min[H]
7 52 18
24 17 30 41 39
26 46 23 44
35
Extracting the Minimum (contd.)
All roots covered by current pointer, so done
Now find the minimum among the roots and make
min[H] point to it (already pointing to minimum in this
example) min[H]
Final heap is
7 52 18
24 17 30 41 39
26 46 23 44
35
Amortized Cost of Extracting Min
Recall that
D(n) = max degree of any node in the heap with n nodes
t(H) = number of trees in heap H
m(H) = number of marked nodes in heap H
Potential function Φ(H) = t(H) + 2m(H)
Actual Cost
Time for Step 1:
O(D(n)) work adding min's children into root list
Time for Step 2 (consolidating trees)
Size of root list just before Step 2 is ≤ D(n) + t(H) - 1
t(H) original roots before deletion minus the one deleted
plus the number of children of the deleted node
The maximum number of merges possible is the no. of nodes
in the root list
Each merge takes O(1) time
So total O(D(n) + t(H)) time for consoildation
O(D(n)) time to find the new min and updating min[H] after
consolidation, since at most D(n) + 1 nodes in root list
Total actual cost = time for Step 1 + time for Step 2
= O(D(n) + t(H))
Potential before extracting minimum = t(H) + 2m(H)
Potential after extracting minimum ≤ (D(n) + 1) + 2m(H)
At most D(n) + 1 roots are there after deletion
No new node is marked during deletion
Can be unmarked, but not marked
Amortized cost = actual cost + potential change
= O(D(n)+ t(H)) + ((D(n)+1) +2m(H)) – (t(H) + 2m(H))
= O(D(n))
But D(n) can be O(n), right? That seems too costly! So is
O(D(n)) any good?
Can show that D(n) = O(lg n) (proof omitted)
So amortized cost = O(lg n)
Decrease Key
Decrease key of element x to k
Case 0: min-heap property not violated
decrease key of x to k
change heap min pointer if necessary
min[H]
7 18 38
24 17 23 21 39 41
26 46
45 30 52
Decrease 46 to 45
35 88 72
Case 1: parent of x is unmarked
decrease key of x to k
cut off link between x and its parent, unmark x if marked
mark parent
add tree rooted at x to root list, updating heap min pointer
min[H]
7 18 38
24 17 23 21 39 41
26 45
15 30 52
Decrease 45 to 15
35 88 72
Case 1: parent of x is unmarked
decrease key of x to k
cut off link between x and its parent, unmark x if marked
mark parent
add tree rooted at x to root list, updating heap min pointer
min[H]
7 18 38
24 17 23 21 39 41
26 15 30 52
Decrease 45 to 15
35 88 72
Case 1: parent of x is unmarked
decrease key of x to k
cut off link between x and its parent, unmark x if marked
mark parent
add tree rooted at x to root list, updating heap min pointer
min[H]
15 7 18 38
72 24 17 23 21 39 41
26 30 52
Decrease 45 to 15
35 88
Case 2: parent of x is marked
decrease key of x to k
cut off link between x and its parent p[x], add x to root list, unmark x if
marked
cut off link between p[x] and p[p[x]], add p[x] to root list, unmark p[x] if
marked
If p[p[x]] unmarked, then mark it and stop
If p[p[x]] marked, cut off p[p[x]], unmark, and repeat until unmarked
node found or root reached min[H]
15 7 18 38
72 p[p[x]] 24 17 23 21 39 41
p[x] 26 30 52
Decrease 35 to 5
x 35
5 88
Case 2: parent of x is marked
decrease key of x to k
cut off link between x and its parent p[x], add x to root list, unmark x if
marked
cut off link between p[x] and p[p[x]], add p[x] to root list, unmark p[x] if
marked
If p[p[x]] unmarked, then mark it and stop
If p[p[x]] marked, cut off p[p[x]], unmark, and repeat until unmarked
node found or root reached min[H]
15 5 7 18 38
x
72 p[p[x]] 24 17 23 21 39 41
p[x] 26 30 52
Decrease 35 to 5
88
Case 2: parent of x is marked
decrease key of x to k
cut off link between x and its parent p[x], add x to root list, unmark x if
marked
cut off link between p[x] and p[p[x]], add p[x] to root list, unmark p[x] if
marked
If p[p[x]] unmarked, then mark it and stop
If p[p[x]] marked, cut off p[p[x]], unmark, and repeat until unmarked
node found or root reached
min[H]
15 5 26 7 18 38
p[x]
x
72 88 24 17 23 21 39 41
p[p[x]]
30 52
Decrease 35 to 5
Case 2: parent of x is marked
decrease key of x to k
cut off link between x and its parent p[x], add x to root list, unmark x if
marked
cut off link between p[x] and p[p[x]], add p[x] to root list, unmark p[x] if
marked
If p[p[x]] unmarked, then mark it and stop
If p[p[x]] marked, cut off p[p[x]], unmark, and repeat until unmarked
node found or root reached (cascading cut)
min[H]
15 5 26 24 7 18 38
72 88 17 23 21 39 41
CASCADING-CUT(H, y)
1. z ← p[y]
2. if z ≠ NIL
3. if mark[y] = FALSE
4. mark[y] = TRUE
5. else CUT(H, y, z)
6. CASCADING-CUT(H, z)
Amortized Cost of Decrease Key
Actual cost
O(1) time for decreasing key value, and the first cut of x
O(1) time for each of c cascading cuts, plus reinserting in root
list
Total O(c)
Change in Potential
H = tree just before decreasing key, H’ just after
t(H') = t(H) + c
t(H) + (c-1) trees from the cascading cut + the tree rotted at x
m(H') ≤ m(H) – c + 2
Each cascading cut unmarks a node except the last one (–(c – 1))
Last cascading cut could potentially mark a node (+1)
Change in potential
= (t(H’) + 2m(H’)) – (t(H) + 2m(H))
≤ c + 2(– c + 2) = 4 – c
Amortized cost
O(1) for decrease-key.
O(D(n)) for delete-min.
Total O(D(n))
Again, can show that D(n) = O(lg n)
So amortized cost of delete = O(lg n)