Skip to content

Commit 75204e8

Browse files
committed
Add Fibonacci Heap implementation
- Implemented `FibonacciHeap` with core operations: `insert`, `extract_min`, `decrease_key`, and `delete`. - Added `Node` class for heap node structure. - Optimized for amortized time complexity with O(1) inserts and O(log n) extract min. - Included example usage and basic documentation.
1 parent dba8eec commit 75204e8

File tree

2 files changed

+1844
-0
lines changed

2 files changed

+1844
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
class Node:
2+
def __init__(self, key):
3+
self.key = key # The key value of the node
4+
self.degree = 0 # The degree of the node (number of children)
5+
self.parent = None # Pointer to the parent node
6+
self.child = None # Pointer to the child node
7+
self.is_marked = False # Indicates if the node is marked
8+
self.next = self # Pointer to the next node in the circular list
9+
self.prev = self # Pointer to the previous node in the circular list
10+
11+
class FibonacciHeap:
12+
def __init__(self):
13+
self.min_node = None # Pointer to the minimum node
14+
self.num_nodes = 0 # Number of nodes in the heap
15+
16+
def insert(self, key):
17+
"""Insert a new node with the given key."""
18+
new_node = Node(key)
19+
self._insert_to_root_list(new_node)
20+
if self.min_node is None or key < self.min_node.key:
21+
self.min_node = new_node
22+
self.num_nodes += 1
23+
24+
def _insert_to_root_list(self, node):
25+
"""Insert a node to the root list of the heap."""
26+
if self.min_node is None:
27+
self.min_node = node
28+
else:
29+
# Add node to the root list
30+
node.prev = self.min_node.prev
31+
node.next = self.min_node
32+
self.min_node.prev.next = node
33+
self.min_node.prev = node
34+
35+
def extract_min(self):
36+
"""Remove and return the node with the minimum key."""
37+
min_node = self.min_node
38+
if min_node is not None:
39+
# Remove min_node from the root list
40+
if min_node.child is not None:
41+
# Add children of min_node to the root list
42+
child = min_node.child
43+
while True:
44+
next_child = child.next
45+
self._insert_to_root_list(child)
46+
child.parent = None
47+
if next_child == min_node.child:
48+
break
49+
child = next_child
50+
51+
# Remove min_node from root list
52+
if min_node == min_node.next:
53+
self.min_node = None # Heap is now empty
54+
else:
55+
min_node.prev.next = min_node.next
56+
min_node.next.prev = min_node.prev
57+
self.min_node = min_node.next
58+
59+
self.num_nodes -= 1
60+
if self.min_node is not None:
61+
self._consolidate()
62+
return min_node.key if min_node else None
63+
64+
def _consolidate(self):
65+
"""Consolidate trees of equal degree in the root list."""
66+
degree_list = [None] * (self.num_nodes + 1)
67+
current = self.min_node
68+
nodes = []
69+
70+
# Store all nodes in a list
71+
while True:
72+
nodes.append(current)
73+
current = current.next
74+
if current == self.min_node:
75+
break
76+
77+
for node in nodes:
78+
degree = node.degree
79+
while degree_list[degree] is not None:
80+
other = degree_list[degree]
81+
if node.key > other.key:
82+
node, other = other, node
83+
self._link(other, node)
84+
degree_list[degree] = None
85+
degree += 1
86+
degree_list[degree] = node
87+
88+
self.min_node = None
89+
for node in degree_list:
90+
if node is not None:
91+
if self.min_node is None:
92+
self.min_node = node
93+
elif node.key < self.min_node.key:
94+
self.min_node = node
95+
96+
def _link(self, node1, node2):
97+
"""Link node1 as a child of node2."""
98+
node1.prev.next = node1.next
99+
node1.next.prev = node1.prev
100+
node1.parent = node2
101+
if node2.child is None:
102+
node2.child = node1
103+
node1.next = node1
104+
node1.prev = node1
105+
else:
106+
# Insert node1 into the child list of node2
107+
node1.prev = node2.child.prev
108+
node1.next = node2.child
109+
node2.child.prev.next = node1
110+
node2.child.prev = node1
111+
node2.degree += 1
112+
node1.is_marked = False
113+
114+
def decrease_key(self, node, new_key):
115+
"""Decrease the key of a given node."""
116+
if new_key > node.key:
117+
raise ValueError("New key is greater than current key")
118+
119+
node.key = new_key
120+
parent = node.parent
121+
122+
if parent is not None and node.key < parent.key:
123+
self._cut(node, parent)
124+
self._insert_to_root_list(node)
125+
if node.key < self.min_node.key:
126+
self.min_node = node
127+
128+
def _cut(self, node, parent):
129+
"""Cut the node from its parent and add it to the root list."""
130+
if node == parent.child:
131+
parent.child = node.next if node.next != node else None
132+
if parent.child is None:
133+
parent.degree -= 1
134+
else:
135+
parent.degree -= 1
136+
node.prev.next = node.next
137+
node.next.prev = node.prev
138+
139+
node.prev = self.min_node.prev
140+
node.next = self.min_node
141+
self.min_node.prev.next = node
142+
self.min_node.prev = node
143+
node.parent = None
144+
node.is_marked = False
145+
146+
def delete(self, node):
147+
"""Delete a node from the heap."""
148+
self.decrease_key(node, float('-inf')) # Decrease the key to -infinity
149+
self.extract_min() # Extract the minimum node
150+
151+
def is_empty(self):
152+
"""Check if the heap is empty."""
153+
return self.min_node is None
154+
155+
def size(self):
156+
"""Return the number of nodes in the heap."""
157+
return self.num_nodes
158+
159+
def min(self):
160+
"""Return the minimum key without removing it."""
161+
return self.min_node.key if self.min_node else None
162+
163+
# Example Usage
164+
if __name__ == "__main__":
165+
fib_heap = FibonacciHeap()
166+
fib_heap.insert(10)
167+
fib_heap.insert(2)
168+
fib_heap.insert(5)
169+
fib_heap.insert(7)
170+
171+
print("Minimum:", fib_heap.min()) # Output: Minimum: 2
172+
print("Extracted Min:", fib_heap.extract_min()) # Output: Extracted Min: 2
173+
print("New Minimum:", fib_heap.min()) # Output: New Minimum: 5

0 commit comments

Comments
 (0)