2
2
Fibonacci Heap
3
3
A more efficient priority queue implementation that provides amortized time bounds
4
4
that are better than those of the binary and binomial heaps.
5
+ reference: https://en.wikipedia.org/wiki/Fibonacci_heap
5
6
6
7
Operations supported:
7
8
- Insert: O(1) amortized
11
12
- Merge: O(1)
12
13
"""
13
14
14
-
15
15
class Node :
16
16
"""
17
- Node in a Fibonacci heap containing:
18
- - value
19
- - parent, child, and sibling links
20
- - degree (number of children)
21
- - mark (whether the node has lost a child since
22
- becoming a child of its current parent)
17
+ A node in a Fibonacci heap.
18
+
19
+ Args:
20
+ val: The value stored in the node.
21
+
22
+ Attributes:
23
+ val: The value stored in the node.
24
+ parent: Reference to parent node.
25
+ child: Reference to one child node.
26
+ left: Reference to left sibling.
27
+ right: Reference to right sibling.
28
+ degree: Number of children.
29
+ mark: Boolean indicating if node has lost a child.
23
30
"""
24
-
25
31
def __init__ (self , val ):
26
32
self .val = val
27
33
self .parent = None
@@ -32,14 +38,24 @@ def __init__(self, val):
32
38
self .mark = False
33
39
34
40
def add_sibling (self , node ):
35
- """Add node as a sibling"""
41
+ """
42
+ Adds a node as a sibling to the current node.
43
+
44
+ Args:
45
+ node: The node to add as a sibling.
46
+ """
36
47
node .left = self
37
48
node .right = self .right
38
49
self .right .left = node
39
50
self .right = node
40
51
41
52
def add_child (self , node ):
42
- """Add node as a child"""
53
+ """
54
+ Adds a node as a child of the current node.
55
+
56
+ Args:
57
+ node: The node to add as a child.
58
+ """
43
59
node .parent = self
44
60
if not self .child :
45
61
self .child = node
@@ -48,38 +64,65 @@ def add_child(self, node):
48
64
self .degree += 1
49
65
50
66
def remove (self ):
51
- """Remove this node from its sibling list"""
67
+ """Removes this node from its sibling list. """
52
68
self .left .right = self .right
53
69
self .right .left = self .left
54
70
55
71
56
72
class FibonacciHeap :
57
73
"""
58
- Min-oriented Fibonacci heap implementation.
74
+ A Fibonacci heap implementation providing
75
+ amortized efficient priority queue operations.
76
+
77
+ This implementation provides the following time complexities:
78
+ - Insert: O(1) amortized
79
+ - Find minimum: O(1)
80
+ - Delete minimum: O(log n) amortized
81
+ - Decrease key: O(1) amortized
82
+ - Merge: O(1)
59
83
60
84
Example:
61
85
>>> heap = FibonacciHeap()
62
- >>> heap.insert(3)
63
- >>> heap.insert(2)
64
- >>> heap.insert(15)
86
+ >>> node1 = heap.insert(3)
87
+ >>> node2 = heap.insert(2)
88
+ >>> node3 = heap.insert(15)
65
89
>>> heap.peek()
66
90
2
67
91
>>> heap.delete_min()
68
92
2
69
93
>>> heap.peek()
70
94
3
95
+ >>> other_heap = FibonacciHeap()
96
+ >>> node4 = other_heap.insert(1)
97
+ >>> heap.merge_heaps(other_heap)
98
+ >>> heap.peek()
99
+ 1
71
100
"""
72
101
73
102
def __init__ (self ):
103
+ """Initializes an empty Fibonacci heap."""
74
104
self .min_node = None
75
105
self .size = 0
76
106
77
107
def is_empty (self ):
78
- """Return True if heap is empty"""
108
+ """
109
+ Checks if the heap is empty.
110
+
111
+ Returns:
112
+ bool: True if heap is empty, False otherwise.
113
+ """
79
114
return self .min_node is None
80
115
81
116
def insert (self , val ):
82
- """Insert a new key into the heap"""
117
+ """
118
+ Inserts a new value into the heap.
119
+
120
+ Args:
121
+ val: Value to insert.
122
+
123
+ Returns:
124
+ Node: The newly created node.
125
+ """
83
126
node = Node (val )
84
127
if not self .min_node :
85
128
self .min_node = node
@@ -91,13 +134,26 @@ def insert(self, val):
91
134
return node
92
135
93
136
def peek (self ):
94
- """Return minimum value without removing it"""
137
+ """
138
+ Returns the minimum value without removing it.
139
+
140
+ Returns:
141
+ The minimum value in the heap.
142
+
143
+ Raises:
144
+ IndexError: If the heap is empty.
145
+ """
95
146
if not self .min_node :
96
147
raise IndexError ("Heap is empty" )
97
148
return self .min_node .val
98
149
99
150
def merge_heaps (self , other ):
100
- """Merge another Fibonacci heap with this one"""
151
+ """
152
+ Merges another Fibonacci heap into this one.
153
+
154
+ Args:
155
+ other: Another FibonacciHeap instance to merge with this one.
156
+ """
101
157
if not other .min_node :
102
158
return
103
159
if not self .min_node :
@@ -115,7 +171,13 @@ def merge_heaps(self, other):
115
171
self .size += other .size
116
172
117
173
def __link_trees (self , node1 , node2 ):
118
- """Link two trees of same degree"""
174
+ """
175
+ Links two trees of same degree.
176
+
177
+ Args:
178
+ node1: First tree's root node.
179
+ node2: Second tree's root node.
180
+ """
119
181
node1 .remove ()
120
182
if node2 .child :
121
183
node2 .child .add_sibling (node1 )
@@ -126,7 +188,15 @@ def __link_trees(self, node1, node2):
126
188
node1 .mark = False
127
189
128
190
def delete_min (self ):
129
- """Remove and return the minimum value"""
191
+ """
192
+ Removes and returns the minimum value from the heap.
193
+
194
+ Returns:
195
+ The minimum value that was removed.
196
+
197
+ Raises:
198
+ IndexError: If the heap is empty.
199
+ """
130
200
if not self .min_node :
131
201
raise IndexError ("Heap is empty" )
132
202
@@ -156,8 +226,12 @@ def delete_min(self):
156
226
return min_val
157
227
158
228
def __consolidate (self ):
159
- """Consolidate trees after delete_min"""
160
- max_degree = int (self .size ** 0.5 ) + 1
229
+ """
230
+ Consolidates the trees in the heap after a delete_min operation.
231
+
232
+ This is an internal method that maintains the heap's structure.
233
+ """
234
+ max_degree = int (self .size ** 0.5 ) + 1
161
235
degree_table = [None ] * max_degree
162
236
163
237
# Collect all roots
@@ -195,7 +269,16 @@ def __consolidate(self):
195
269
self .min_node = degree_table [degree ]
196
270
197
271
def decrease_key (self , node , new_val ):
198
- """Decrease the value of a node"""
272
+ """
273
+ Decreases the value of a node.
274
+
275
+ Args:
276
+ node: The node whose value should be decreased.
277
+ new_val: The new value for the node.
278
+
279
+ Raises:
280
+ ValueError: If new value is greater than current value.
281
+ """
199
282
if new_val > node .val :
200
283
raise ValueError ("New value is greater than current value" )
201
284
@@ -210,7 +293,19 @@ def decrease_key(self, node, new_val):
210
293
self .min_node = node
211
294
212
295
def __cut (self , node , parent ):
213
- """Cut a node from its parent"""
296
+ """
297
+ Cuts a node from its parent.
298
+
299
+ Args:
300
+ node: Node to be cut.
301
+ parent: Parent of the node to be cut.
302
+ """ """
303
+ Performs cascading cut operation.
304
+
305
+ Args:
306
+ node: Starting node for cascading cut.
307
+ """
308
+
214
309
parent .degree -= 1
215
310
if parent .child == node :
216
311
parent .child = node .right if node .right != node else None
@@ -222,16 +317,28 @@ def __cut(self, node, parent):
222
317
self .min_node .add_sibling (node )
223
318
224
319
def __cascading_cut (self , node ):
225
- """Perform cascading cut operation"""
226
- if parent := node .parent :
320
+ """
321
+ Performs cascading cut operation.
322
+
323
+ Args:
324
+ node: Starting node for cascading cut.
325
+ """
326
+
327
+ parent = node .parent
328
+ if parent :
227
329
if not node .mark :
228
330
node .mark = True
229
331
else :
230
332
self .__cut (node , parent )
231
333
self .__cascading_cut (parent )
232
334
233
335
def __str__ (self ):
234
- """String representation of the heap"""
336
+ """
337
+ Returns a string representation of the heap.
338
+
339
+ Returns:
340
+ str: A string showing the heap structure.
341
+ """
235
342
if not self .min_node :
236
343
return "Empty heap"
237
344
@@ -252,5 +359,4 @@ def print_tree(node, level=0):
252
359
253
360
if __name__ == "__main__" :
254
361
import doctest
255
-
256
362
doctest .testmod ()
0 commit comments