Skip to content

Commit 78653ac

Browse files
committed
Add Fibonacci heap implementation to advanced heap variants
Signed-off-by: Arya Pratap Singh <notaryasingh@gmail.com>
1 parent a71618f commit 78653ac

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
"""Fibonacci Heap implementation - An advanced priority queue data structure.
2+
3+
A Fibonacci heap is a heap data structure consisting of a collection of heap-ordered
4+
trees. It has a better amortized running time than other heap types, particularly for
5+
the decrease-key operation which runs in amortized O(1) time.
6+
7+
This makes Fibonacci heaps ideal for algorithms like Dijkstra's shortest path and
8+
Prim's minimum spanning tree algorithm.
9+
10+
For more information, see: https://en.wikipedia.org/wiki/Fibonacci_heap
11+
12+
Time Complexity (amortized):
13+
- Insert: O(1)
14+
- Find minimum: O(1)
15+
- Delete minimum: O(log n)
16+
- Decrease key: O(1)
17+
- Merge: O(1)
18+
19+
Space Complexity: O(n)
20+
"""
21+
22+
from __future__ import annotations
23+
24+
from typing import Any
25+
26+
27+
class FibonacciNode:
28+
"""A node in the Fibonacci heap."""
29+
30+
def __init__(self, key: Any, value: Any = None) -> None:
31+
self.key = key # Priority key
32+
self.value = value # Associated data
33+
self.parent: FibonacciNode | None = None
34+
self.child: FibonacciNode | None = None
35+
self.left: FibonacciNode | None = None # Left sibling
36+
self.right: FibonacciNode | None = None # Right sibling
37+
self.degree = 0 # Number of children
38+
self.marked = False # Whether node has lost a child since becoming a child
39+
40+
41+
class FibonacciHeap:
42+
"""
43+
Fibonacci Heap implementation - Advanced priority queue.
44+
45+
This implementation provides amortized O(1) decrease-key operations,
46+
making it suitable for algorithms requiring frequent priority updates.
47+
48+
Example:
49+
>>> heap = FibonacciHeap()
50+
>>> heap.insert(10, "ten")
51+
>>> heap.insert(5, "five")
52+
>>> heap.insert(15, "fifteen")
53+
>>> heap.find_min()
54+
(5, 'five')
55+
>>> heap.extract_min()
56+
(5, 'five')
57+
>>> heap.find_min()
58+
(10, 'ten')
59+
"""
60+
61+
def __init__(self) -> None:
62+
"""Initialize an empty Fibonacci heap."""
63+
self.min_node: FibonacciNode | None = None
64+
self.total_nodes = 0
65+
66+
def __bool__(self) -> bool:
67+
"""Return True if the heap is not empty."""
68+
return self.min_node is not None
69+
70+
def __len__(self) -> int:
71+
"""Return the number of nodes in the heap."""
72+
return self.total_nodes
73+
74+
def is_empty(self) -> bool:
75+
"""Check if the heap is empty."""
76+
return self.min_node is None
77+
78+
def insert(self, key: Any, value: Any = None) -> None:
79+
"""Insert a new key-value pair into the heap."""
80+
node = FibonacciNode(key, value)
81+
if not self.min_node:
82+
self.min_node = node
83+
node.left = node
84+
node.right = node
85+
else:
86+
# Insert into root list
87+
node.left = self.min_node
88+
node.right = self.min_node.right
89+
self.min_node.right.left = node
90+
self.min_node.right = node
91+
if key < self.min_node.key:
92+
self.min_node = node
93+
self.total_nodes += 1
94+
95+
def find_min(self):
96+
"""Find the minimum key-value pair without removing it."""
97+
if not self.min_node:
98+
return None
99+
return (self.min_node.key, self.min_node.value)
100+
101+
def extract_min(self):
102+
"""Extract and return the minimum key-value pair."""
103+
if not self.min_node:
104+
return None
105+
106+
min_node = self.min_node
107+
result = (min_node.key, min_node.value)
108+
109+
# Handle children
110+
if min_node.child:
111+
child = min_node.child
112+
while True:
113+
next_child = child.right
114+
# Add child to root list
115+
child.left = min_node.left
116+
child.right = min_node.right
117+
min_node.left.right = child
118+
min_node.right.left = child
119+
child.parent = None
120+
child = next_child
121+
if child == min_node.child:
122+
break
123+
124+
# Remove min_node from root list
125+
if min_node.left == min_node:
126+
self.min_node = None
127+
else:
128+
min_node.left.right = min_node.right
129+
min_node.right.left = min_node.left
130+
self.min_node = min_node.right
131+
# Find new minimum
132+
current = self.min_node
133+
min_key = current.key
134+
start = current
135+
current = current.right
136+
while current != start:
137+
if current.key < min_key:
138+
min_key = current.key
139+
self.min_node = current
140+
current = current.right
141+
142+
self.total_nodes -= 1
143+
return result
144+
145+
def merge(self, other):
146+
"""Merge this heap with another Fibonacci heap."""
147+
if not other.min_node:
148+
return self
149+
if not self.min_node:
150+
self.min_node = other.min_node
151+
self.total_nodes = other.total_nodes
152+
return self
153+
154+
# Merge root lists
155+
self.min_node.left.right = other.min_node.right
156+
other.min_node.right.left = self.min_node.left
157+
self.min_node.left = other.min_node.left
158+
other.min_node.left.right = self.min_node
159+
160+
# Update minimum
161+
if other.min_node.key < self.min_node.key:
162+
self.min_node = other.min_node
163+
164+
self.total_nodes += other.total_nodes
165+
return self

0 commit comments

Comments
 (0)