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