@@ -47,8 +47,9 @@ export class MinHeap<T> {
4747 */
4848 insert ( element : T , priority : number ) : void {
4949 const entry : HeapEntry < T > = { element, priority } ;
50- this . heap . push ( entry ) ;
51- const index = this . heap . length - 1 ;
50+ const heap = this . heap ;
51+ heap . push ( entry ) ;
52+ const index = heap . length - 1 ;
5253 this . positions . set ( element , index ) ;
5354 this . bubbleUp ( index ) ;
5455 }
@@ -58,27 +59,33 @@ export class MinHeap<T> {
5859 * @returns Option containing the minimum element, or None if heap is empty
5960 */
6061 extractMin ( ) : Option < T > {
61- if ( this . heap . length === 0 ) {
62+ const heap = this . heap ;
63+ const heapLength = heap . length ;
64+
65+ if ( heapLength === 0 ) {
6266 return None ( ) ;
6367 }
6468
65- const min = this . heap [ 0 ] ;
66- this . positions . delete ( min . element ) ;
69+ const min = heap [ 0 ] ;
70+ const minElement = min . element ;
71+ this . positions . delete ( minElement ) ;
6772
68- if ( this . heap . length === 1 ) {
69- this . heap = [ ] ;
70- return Some ( min . element ) ;
73+ if ( heapLength === 1 ) {
74+ heap . length = 0 ; // Faster than reassignment
75+ return Some ( minElement ) ;
7176 }
7277
7378 // Move last element to root and bubble down
74- const last = this . heap . pop ( ) ;
75- if ( last !== undefined ) {
76- this . heap [ 0 ] = last ;
77- this . positions . set ( last . element , 0 ) ;
78- this . bubbleDown ( 0 ) ;
79+ const last = heap . pop ( ) ;
80+ if ( last === undefined ) {
81+ // This should never happen since we checked heapLength > 1
82+ return None ( ) ;
7983 }
84+ heap [ 0 ] = last ;
85+ this . positions . set ( last . element , 0 ) ;
86+ this . bubbleDown ( 0 ) ;
8087
81- return Some ( min . element ) ;
88+ return Some ( minElement ) ;
8289 }
8390
8491 /**
@@ -97,7 +104,8 @@ export class MinHeap<T> {
97104 } ) ;
98105 }
99106
100- const currentPriority = this . heap [ index ] . priority ;
107+ const heap = this . heap ;
108+ const currentPriority = heap [ index ] . priority ;
101109
102110 if ( newPriority > currentPriority ) {
103111 return Err ( {
@@ -106,7 +114,7 @@ export class MinHeap<T> {
106114 } ) ;
107115 }
108116
109- this . heap [ index ] . priority = newPriority ;
117+ heap [ index ] . priority = newPriority ;
110118 this . bubbleUp ( index ) ;
111119
112120 return Ok ( void 0 ) ;
@@ -128,23 +136,66 @@ export class MinHeap<T> {
128136 return this . heap . length ;
129137 }
130138
139+ /**
140+ * Extract multiple elements efficiently (optimized for performance tests).
141+ * Returns array of extracted elements to avoid Option wrapper overhead.
142+ * @param count
143+ * @internal
144+ */
145+ extractMinBatch ( count : number ) : T [ ] {
146+ const result : T [ ] = [ ] ;
147+ const heap = this . heap ;
148+
149+ for ( let i = 0 ; i < count && heap . length > 0 ; i ++ ) {
150+ const min = heap [ 0 ] ;
151+ result . push ( min . element ) ;
152+ this . positions . delete ( min . element ) ;
153+
154+ if ( heap . length === 1 ) {
155+ heap . length = 0 ;
156+ break ;
157+ }
158+
159+ // Move last element to root and bubble down
160+ const last = heap . pop ( ) ;
161+ if ( last === undefined ) {
162+ // This should never happen since we checked heap.length > 1
163+ break ;
164+ }
165+ heap [ 0 ] = last ;
166+ this . positions . set ( last . element , 0 ) ;
167+ this . bubbleDown ( 0 ) ;
168+ }
169+
170+ return result ;
171+ }
172+
131173 /**
132174 * Bubble up an element to maintain heap property.
133175 * @param index
134176 * @internal
135177 */
136178 private bubbleUp ( index : number ) : void {
179+ const heap = this . heap ;
180+ const positions = this . positions ;
181+
137182 while ( index > 0 ) {
138- const parentIndex = Math . floor ( ( index - 1 ) / 2 ) ;
139- const parent = this . heap [ parentIndex ] ;
140- const current = this . heap [ index ] ;
183+ const parentIndex = ( index - 1 ) >> 1 ; // Bitwise divide by 2, faster than Math.floor
184+ const parent = heap [ parentIndex ] ;
185+ const current = heap [ index ] ;
141186
142187 if ( parent . priority <= current . priority ) {
143188 break ; // Heap property satisfied
144189 }
145190
146- // Swap with parent
147- this . swap ( index , parentIndex ) ;
191+ // Inline swap for performance
192+ heap [ index ] = parent ;
193+ heap [ parentIndex ] = current ;
194+
195+ // Update position map
196+ positions . set ( current . element , parentIndex ) ;
197+ positions . set ( parent . element , index ) ;
198+
148199 index = parentIndex ;
149200 }
150201 }
@@ -155,33 +206,45 @@ export class MinHeap<T> {
155206 * @internal
156207 */
157208 private bubbleDown ( index : number ) : void {
209+ const heap = this . heap ;
210+ const positions = this . positions ;
211+ const heapLength = heap . length ;
212+
158213 while ( true ) {
159- const leftChild = 2 * index + 1 ;
160- const rightChild = 2 * index + 2 ;
214+ const leftChild = ( index << 1 ) + 1 ; // Bitwise multiply by 2, faster
215+ const rightChild = leftChild + 1 ;
161216 let smallest = index ;
162217
163218 // Check if left child is smaller
164- if (
165- leftChild < this . heap . length &&
166- this . heap [ leftChild ] . priority < this . heap [ smallest ] . priority
167- ) {
168- smallest = leftChild ;
219+ if ( leftChild < heapLength ) {
220+ const leftPriority = heap [ leftChild ] . priority ;
221+ if ( leftPriority < heap [ smallest ] . priority ) {
222+ smallest = leftChild ;
223+ }
169224 }
170225
171226 // Check if right child is smaller
172- if (
173- rightChild < this . heap . length &&
174- this . heap [ rightChild ] . priority < this . heap [ smallest ] . priority
175- ) {
176- smallest = rightChild ;
227+ if ( rightChild < heapLength ) {
228+ const rightPriority = heap [ rightChild ] . priority ;
229+ if ( rightPriority < heap [ smallest ] . priority ) {
230+ smallest = rightChild ;
231+ }
177232 }
178233
179234 if ( smallest === index ) {
180235 break ; // Heap property satisfied
181236 }
182237
183- // Swap with smallest child
184- this . swap ( index , smallest ) ;
238+ // Inline swap for performance
239+ const current = heap [ index ] ;
240+ const swapTarget = heap [ smallest ] ;
241+ heap [ index ] = swapTarget ;
242+ heap [ smallest ] = current ;
243+
244+ // Update position map
245+ positions . set ( current . element , smallest ) ;
246+ positions . set ( swapTarget . element , index ) ;
247+
185248 index = smallest ;
186249 }
187250 }
@@ -191,14 +254,18 @@ export class MinHeap<T> {
191254 * @param i
192255 * @param j
193256 * @internal
257+ * @deprecated Use inline swaps in bubbleUp/bubbleDown for better performance
194258 */
195259 private swap ( i : number , j : number ) : void {
196- const temp = this . heap [ i ] ;
197- this . heap [ i ] = this . heap [ j ] ;
198- this . heap [ j ] = temp ;
260+ const heap = this . heap ;
261+ const positions = this . positions ;
262+
263+ const temp = heap [ i ] ;
264+ heap [ i ] = heap [ j ] ;
265+ heap [ j ] = temp ;
199266
200267 // Update position map
201- this . positions . set ( this . heap [ i ] . element , i ) ;
202- this . positions . set ( this . heap [ j ] . element , j ) ;
268+ positions . set ( heap [ i ] . element , i ) ;
269+ positions . set ( heap [ j ] . element , j ) ;
203270 }
204271}
0 commit comments