linked-list-typed 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +14 -14
  2. package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
  3. package/dist/data-structures/base/iterable-element-base.js +149 -107
  4. package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
  5. package/dist/data-structures/base/iterable-entry-base.js +59 -116
  6. package/dist/data-structures/base/linear-base.d.ts +250 -192
  7. package/dist/data-structures/base/linear-base.js +137 -274
  8. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  9. package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
  10. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  11. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  12. package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
  13. package/dist/data-structures/binary-tree/avl-tree.js +208 -195
  14. package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
  15. package/dist/data-structures/binary-tree/binary-tree.js +612 -879
  16. package/dist/data-structures/binary-tree/bst.d.ts +258 -306
  17. package/dist/data-structures/binary-tree/bst.js +505 -481
  18. package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  19. package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
  20. package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
  21. package/dist/data-structures/binary-tree/tree-counter.js +172 -203
  22. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  23. package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
  24. package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
  25. package/dist/data-structures/graph/abstract-graph.js +267 -237
  26. package/dist/data-structures/graph/directed-graph.d.ts +108 -224
  27. package/dist/data-structures/graph/directed-graph.js +146 -233
  28. package/dist/data-structures/graph/map-graph.d.ts +49 -55
  29. package/dist/data-structures/graph/map-graph.js +56 -59
  30. package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
  31. package/dist/data-structures/graph/undirected-graph.js +129 -149
  32. package/dist/data-structures/hash/hash-map.d.ts +164 -338
  33. package/dist/data-structures/hash/hash-map.js +270 -457
  34. package/dist/data-structures/heap/heap.d.ts +214 -289
  35. package/dist/data-structures/heap/heap.js +340 -349
  36. package/dist/data-structures/heap/max-heap.d.ts +11 -47
  37. package/dist/data-structures/heap/max-heap.js +11 -66
  38. package/dist/data-structures/heap/min-heap.d.ts +12 -47
  39. package/dist/data-structures/heap/min-heap.js +11 -66
  40. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  41. package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
  42. package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  43. package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
  44. package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  45. package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
  46. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  47. package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
  48. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  49. package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
  50. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
  51. package/dist/data-structures/priority-queue/priority-queue.js +8 -83
  52. package/dist/data-structures/queue/deque.d.ts +227 -254
  53. package/dist/data-structures/queue/deque.js +309 -348
  54. package/dist/data-structures/queue/queue.d.ts +180 -201
  55. package/dist/data-structures/queue/queue.js +265 -248
  56. package/dist/data-structures/stack/stack.d.ts +124 -102
  57. package/dist/data-structures/stack/stack.js +181 -125
  58. package/dist/data-structures/trie/trie.d.ts +164 -165
  59. package/dist/data-structures/trie/trie.js +189 -172
  60. package/dist/interfaces/binary-tree.d.ts +56 -6
  61. package/dist/interfaces/graph.d.ts +16 -0
  62. package/dist/types/data-structures/base/base.d.ts +1 -1
  63. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
  64. package/dist/types/utils/utils.d.ts +6 -6
  65. package/dist/utils/utils.d.ts +110 -49
  66. package/dist/utils/utils.js +148 -73
  67. package/package.json +2 -2
  68. package/src/data-structures/base/iterable-element-base.ts +238 -115
  69. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  70. package/src/data-structures/base/linear-base.ts +271 -277
  71. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  72. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  73. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  74. package/src/data-structures/binary-tree/binary-tree.ts +681 -905
  75. package/src/data-structures/binary-tree/bst.ts +568 -570
  76. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  77. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  78. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  79. package/src/data-structures/graph/abstract-graph.ts +339 -264
  80. package/src/data-structures/graph/directed-graph.ts +146 -236
  81. package/src/data-structures/graph/map-graph.ts +63 -60
  82. package/src/data-structures/graph/undirected-graph.ts +129 -152
  83. package/src/data-structures/hash/hash-map.ts +274 -496
  84. package/src/data-structures/heap/heap.ts +389 -402
  85. package/src/data-structures/heap/max-heap.ts +12 -76
  86. package/src/data-structures/heap/min-heap.ts +13 -76
  87. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  88. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  89. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  90. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  91. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  92. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  93. package/src/data-structures/queue/deque.ts +381 -357
  94. package/src/data-structures/queue/queue.ts +310 -264
  95. package/src/data-structures/stack/stack.ts +217 -131
  96. package/src/data-structures/trie/trie.ts +240 -175
  97. package/src/interfaces/binary-tree.ts +240 -6
  98. package/src/interfaces/graph.ts +37 -0
  99. package/src/types/data-structures/base/base.ts +5 -5
  100. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  101. package/src/types/utils/utils.ts +9 -5
  102. package/src/utils/utils.ts +152 -86
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * data-structure-typed
3
- * @author Kirk Qi
4
- * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
5
6
  * @license MIT License
6
7
  */
7
8
 
@@ -9,6 +10,10 @@ import type { Comparator, DFSOrderPattern, ElementCallback, HeapOptions } from '
9
10
  import { IterableElementBase } from '../base';
10
11
 
11
12
  /**
13
+ * Binary heap with pluggable comparator; supports fast insertion and removal of the top element.
14
+ * @remarks Time O(1), Space O(1)
15
+ * @template E
16
+ * @template R
12
17
  * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.
13
18
  * 2. Heap Properties: Each node in a heap follows a specific order property, which varies depending on the type of heap:
14
19
  * Max Heap: The value of each parent node is greater than or equal to the value of its children.
@@ -185,21 +190,18 @@ import { IterableElementBase } from '../base';
185
190
  * ]);
186
191
  * console.log(scheduleTasks(tasks, 2)); // expectedMap
187
192
  */
188
- export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
189
- /**
190
- * The constructor initializes a heap data structure with optional elements and options.
191
- * @param elements - The `elements` parameter is an iterable object that contains the initial
192
- * elements to be added to the heap.
193
- * It is an optional parameter, and if not provided, the heap will
194
- * be initialized as empty.
195
- * @param [options] - The `options` parameter is an optional object that can contain additional
196
- * configuration options for the heap.
197
- * In this case, it is used to specify a custom comparator
198
- * function for comparing elements in the heap.
199
- * The comparator function is used to determine the
200
- * order of elements in the heap.
201
- */
202
- constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {
193
+ export class Heap<E = unknown, R = never> extends IterableElementBase<E, R> {
194
+ protected _equals: (a: E, b: E) => boolean = Object.is;
195
+
196
+ /**
197
+ * Create a Heap and optionally bulk-insert elements.
198
+ * @remarks Time O(N), Space O(N)
199
+ * @param [elements] - Iterable of elements (or raw values if toElementFn is set).
200
+ * @param [options] - Options such as comparator and toElementFn.
201
+ * @returns New Heap instance.
202
+ */
203
+
204
+ constructor(elements: Iterable<E | R> = [], options?: HeapOptions<E, R>) {
203
205
  super(options);
204
206
 
205
207
  if (options) {
@@ -207,91 +209,113 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
207
209
  if (comparator) this._comparator = comparator;
208
210
  }
209
211
 
210
- this.addMany(elements);
212
+ this.addMany(elements as Iterable<E | R>);
211
213
  }
212
214
 
213
215
  protected _elements: E[] = [];
214
216
 
215
217
  /**
216
- * The function returns an array of elements.
217
- * @returns The element array is being returned.
218
+ * Get the backing array of the heap.
219
+ * @remarks Time O(1), Space O(1)
220
+ * @returns Internal elements array.
218
221
  */
222
+
219
223
  get elements(): E[] {
220
224
  return this._elements;
221
225
  }
222
226
 
223
227
  /**
224
- * Get the size (number of elements) of the heap.
228
+ * Get the number of elements.
229
+ * @remarks Time O(1), Space O(1)
230
+ * @returns Heap size.
225
231
  */
232
+
226
233
  get size(): number {
227
234
  return this.elements.length;
228
235
  }
229
236
 
230
237
  /**
231
- * Get the last element in the heap, which is not necessarily a leaf node.
232
- * @returns The last element or undefined if the heap is empty.
238
+ * Get the last leaf element.
239
+ * @remarks Time O(1), Space O(1)
240
+ * @returns Last element or undefined.
233
241
  */
242
+
234
243
  get leaf(): E | undefined {
235
244
  return this.elements[this.size - 1] ?? undefined;
236
245
  }
237
246
 
238
247
  /**
239
- * Static method that creates a binary heap from an array of elements and a comparison function.
240
- * @returns A new Heap instance.
241
- * @param elements
242
- * @param options
248
+ * Create a heap of the same class from an iterable.
249
+ * @remarks Time O(N), Space O(N)
250
+ * @template T
251
+ * @template R
252
+ * @template S
253
+ * @param [elements] - Iterable of elements or raw records.
254
+ * @param [options] - Heap options including comparator.
255
+ * @returns A new heap instance of this class.
256
+ */
257
+
258
+ static from<T, R = never, S extends Heap<T, R> = Heap<T, R>>(
259
+ this: new (elements?: Iterable<T | R>, options?: HeapOptions<T, R>) => S,
260
+ elements?: Iterable<T | R>,
261
+ options?: HeapOptions<T, R>
262
+ ): S {
263
+ return new this(elements, options);
264
+ }
265
+
266
+ /**
267
+ * Build a Heap from an iterable in linear time given a comparator.
268
+ * @remarks Time O(N), Space O(N)
269
+ * @template EE
270
+ * @template RR
271
+ * @param elements - Iterable of elements.
272
+ * @param options - Heap options including comparator.
273
+ * @returns A new Heap built from elements.
243
274
  */
244
- static heapify<E = any, R = any>(elements: Iterable<E>, options: HeapOptions<E, R>): Heap<E> {
245
- return new Heap<E>(elements, options);
275
+
276
+ static heapify<EE = unknown, RR = never>(elements: Iterable<EE>, options: HeapOptions<EE, RR>): Heap<EE, RR> {
277
+ return new Heap<EE, RR>(elements, options);
246
278
  }
247
279
 
248
280
  /**
249
- * Time Complexity: O(log n)
250
- * Space Complexity: O(1)
251
- *
252
- * The add function pushes an element into an array and then triggers a bubble-up operation.
253
- * @param {E} element - The `element` parameter represents the element that you want to add to the
254
- * data structure.
255
- * @returns The `add` method is returning a boolean value, which is the result of calling the
256
- * `_bubbleUp` method with the index `this.elements.length - 1` as an argument.
281
+ * Insert an element.
282
+ * @remarks Time O(1) amortized, Space O(1)
283
+ * @param element - Element to insert.
284
+ * @returns True.
257
285
  */
286
+
258
287
  add(element: E): boolean {
259
- this._elements.push(element as E);
288
+ this._elements.push(element);
260
289
  return this._bubbleUp(this.elements.length - 1);
261
290
  }
262
291
 
263
292
  /**
264
- * Time Complexity: O(k log n)
265
- * Space Complexity: O(1)
266
- *
267
- * The `addMany` function iterates over elements and adds them to a collection, returning an array of
268
- * boolean values indicating success or failure.
269
- * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `addMany` method is
270
- * an iterable containing elements of type `E` or `R`. The method iterates over each element in the
271
- * iterable and adds them to the data structure. If a transformation function `_toElementFn` is
272
- * provided, it transforms the element
273
- * @returns The `addMany` method returns an array of boolean values indicating whether each element
274
- * in the input iterable was successfully added to the data structure.
293
+ * Insert many elements from an iterable.
294
+ * @remarks Time O(N log N), Space O(1)
295
+ * @param elements - Iterable of elements or raw values.
296
+ * @returns Array of per-element success flags.
275
297
  */
276
- addMany(elements: Iterable<E> | Iterable<R>): boolean[] {
277
- const ans: boolean[] = [];
298
+
299
+ addMany(elements: Iterable<E | R>): boolean[] {
300
+ const flags: boolean[] = [];
278
301
  for (const el of elements) {
279
- if (this._toElementFn) {
280
- ans.push(this.add(this._toElementFn(el as R)));
281
- continue;
302
+ if (this.toElementFn) {
303
+ const ok = this.add(this.toElementFn(el as R));
304
+ flags.push(ok);
305
+ } else {
306
+ const ok = this.add(el as E);
307
+ flags.push(ok);
282
308
  }
283
- ans.push(this.add(el as E));
284
309
  }
285
- return ans;
310
+ return flags;
286
311
  }
287
312
 
288
313
  /**
289
- * Time Complexity: O(log n)
290
- * Space Complexity: O(1)
291
- *
292
- * Remove and return the top element (the smallest or largest element) from the heap.
293
- * @returns The top element or undefined if the heap is empty.
314
+ * Remove and return the top element.
315
+ * @remarks Time O(log N), Space O(1)
316
+ * @returns Top element or undefined.
294
317
  */
318
+
295
319
  poll(): E | undefined {
296
320
  if (this.elements.length === 0) return;
297
321
  const value = this.elements[0];
@@ -304,68 +328,74 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
304
328
  }
305
329
 
306
330
  /**
307
- * Time Complexity: O(1)
308
- * Space Complexity: O(1)
309
- *
310
- * Peek at the top element of the heap without removing it.
311
- * @returns The top element or undefined if the heap is empty.
331
+ * Get the current top element without removing it.
332
+ * @remarks Time O(1), Space O(1)
333
+ * @returns Top element or undefined.
312
334
  */
335
+
313
336
  peek(): E | undefined {
314
337
  return this.elements[0];
315
338
  }
316
339
 
317
340
  /**
318
- * Check if the heap is empty.
319
- * @returns True if the heap is empty, otherwise false.
341
+ * Check whether the heap is empty.
342
+ * @remarks Time O(1), Space O(1)
343
+ * @returns True if size is 0.
320
344
  */
345
+
321
346
  isEmpty(): boolean {
322
347
  return this.size === 0;
323
348
  }
324
349
 
325
350
  /**
326
- * Reset the elements of the heap. Make the elements empty.
351
+ * Remove all elements.
352
+ * @remarks Time O(1), Space O(1)
353
+ * @returns void
327
354
  */
355
+
328
356
  clear(): void {
329
357
  this._elements = [];
330
358
  }
331
359
 
332
360
  /**
333
- * Time Complexity: O(n)
334
- * Space Complexity: O(n)
335
- *
336
- * Clear and add elements of the heap
337
- * @param elements
361
+ * Replace the backing array and rebuild the heap.
362
+ * @remarks Time O(N), Space O(N)
363
+ * @param elements - Iterable used to refill the heap.
364
+ * @returns Array of per-node results from fixing steps.
338
365
  */
339
- refill(elements: E[]): boolean[] {
340
- this._elements = elements;
366
+
367
+ refill(elements: Iterable<E>): boolean[] {
368
+ this._elements = Array.from(elements);
341
369
  return this.fix();
342
370
  }
343
371
 
344
372
  /**
345
- * Time Complexity: O(n)
346
- * Space Complexity: O(1)
347
- *
348
- * Use a comparison function to check whether a binary heap contains a specific element.
349
- * @param element - the element to check.
350
- * @returns Returns true if the specified element is contained; otherwise, returns false.
373
+ * Check if an equal element exists in the heap.
374
+ * @remarks Time O(N), Space O(1)
375
+ * @param element - Element to search for.
376
+ * @returns True if found.
351
377
  */
378
+
352
379
  override has(element: E): boolean {
353
- return this.elements.includes(element);
380
+ for (const el of this.elements) if (this._equals(el, element)) return true;
381
+ return false;
354
382
  }
355
383
 
356
384
  /**
357
- * Time Complexity: O(n)
358
- * Space Complexity: O(1)
359
- *
360
- * The `delete` function removes an element from an array-like data structure, maintaining the order
361
- * and structure of the remaining elements.
362
- * @param {E} element - The `element` parameter represents the element that you want to delete from
363
- * the array `this.elements`.
364
- * @returns The `delete` function is returning a boolean value. It returns `true` if the element was
365
- * successfully deleted from the array, and `false` if the element was not found in the array.
385
+ * Delete one occurrence of an element.
386
+ * @remarks Time O(N), Space O(1)
387
+ * @param element - Element to delete.
388
+ * @returns True if an element was removed.
366
389
  */
390
+
367
391
  delete(element: E): boolean {
368
- const index = this.elements.indexOf(element);
392
+ let index = -1;
393
+ for (let i = 0; i < this.elements.length; i++) {
394
+ if (this._equals(this.elements[i], element)) {
395
+ index = i;
396
+ break;
397
+ }
398
+ }
369
399
  if (index < 0) return false;
370
400
  if (index === 0) {
371
401
  this.poll();
@@ -380,17 +410,54 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
380
410
  }
381
411
 
382
412
  /**
383
- * Time Complexity: O(n)
384
- * Space Complexity: O(log n)
385
- *
386
- * Depth-first search (DFS) method, different traversal orders can be selected。
387
- * @param order - Traverse order parameter: 'IN' (in-order), 'PRE' (pre-order) or 'POST' (post-order).
388
- * @returns An array containing elements traversed in the specified order.
413
+ * Delete the first element that matches a predicate.
414
+ * @remarks Time O(N), Space O(1)
415
+ * @param predicate - Function (element, index, heap) → boolean.
416
+ * @returns True if an element was removed.
417
+ */
418
+
419
+ deleteBy(predicate: (element: E, index: number, heap: this) => boolean): boolean {
420
+ let idx = -1;
421
+ for (let i = 0; i < this.elements.length; i++) {
422
+ if (predicate(this.elements[i], i, this)) {
423
+ idx = i;
424
+ break;
425
+ }
426
+ }
427
+ if (idx < 0) return false;
428
+ if (idx === 0) {
429
+ this.poll();
430
+ } else if (idx === this.elements.length - 1) {
431
+ this.elements.pop();
432
+ } else {
433
+ this.elements.splice(idx, 1, this.elements.pop()!);
434
+ this._bubbleUp(idx);
435
+ this._sinkDown(idx, this.elements.length >> 1);
436
+ }
437
+ return true;
438
+ }
439
+
440
+ /**
441
+ * Set the equality comparator used by has/delete operations.
442
+ * @remarks Time O(1), Space O(1)
443
+ * @param equals - Equality predicate (a, b) → boolean.
444
+ * @returns This heap.
445
+ */
446
+
447
+ setEquality(equals: (a: E, b: E) => boolean): this {
448
+ this._equals = equals;
449
+ return this;
450
+ }
451
+
452
+ /**
453
+ * Traverse the binary heap as a complete binary tree and collect elements.
454
+ * @remarks Time O(N), Space O(H)
455
+ * @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
456
+ * @returns Array of visited elements.
389
457
  */
458
+
390
459
  dfs(order: DFSOrderPattern = 'PRE'): E[] {
391
460
  const result: E[] = [];
392
-
393
- // Auxiliary recursive function, traverses the binary heap according to the traversal order
394
461
  const _dfs = (index: number) => {
395
462
  const left = 2 * index + 1,
396
463
  right = left + 1;
@@ -410,153 +477,147 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
410
477
  }
411
478
  }
412
479
  };
413
-
414
- _dfs(0); // Traverse starting from the root node
415
-
480
+ _dfs(0);
416
481
  return result;
417
482
  }
418
483
 
419
484
  /**
420
- * Time Complexity: O(n)
421
- * Space Complexity: O(n)
422
- *
423
- * Clone the heap, creating a new heap with the same elements.
424
- * @returns A new Heap instance containing the same elements.
485
+ * Restore heap order bottom-up (heapify in-place).
486
+ * @remarks Time O(N), Space O(1)
487
+ * @returns Array of per-node results from fixing steps.
425
488
  */
426
- clone(): Heap<E, R> {
427
- return new Heap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });
489
+
490
+ fix(): boolean[] {
491
+ const results: boolean[] = [];
492
+ for (let i = Math.floor(this.size / 2) - 1; i >= 0; i--) {
493
+ results.push(this._sinkDown(i, this.elements.length >> 1));
494
+ }
495
+ return results;
428
496
  }
429
497
 
430
498
  /**
431
- * Time Complexity: O(n log n)
432
- * Space Complexity: O(n)
433
- *
434
- * Sort the elements in the heap and return them as an array.
435
- * @returns An array containing the elements sorted in ascending order.
499
+ * Return all elements in ascending order by repeatedly polling.
500
+ * @remarks Time O(N log N), Space O(N)
501
+ * @returns Sorted array of elements.
436
502
  */
503
+
437
504
  sort(): E[] {
438
- const visitedNode: E[] = [];
439
- const cloned = new Heap<E, R>(this, { comparator: this.comparator });
440
- while (cloned.size !== 0) {
505
+ const visited: E[] = [];
506
+ const cloned = this._createInstance();
507
+ for (const x of this.elements) cloned.add(x);
508
+ while (!cloned.isEmpty()) {
441
509
  const top = cloned.poll();
442
- if (top !== undefined) visitedNode.push(top);
510
+ if (top !== undefined) visited.push(top);
443
511
  }
444
- return visitedNode;
512
+ return visited;
445
513
  }
446
514
 
447
515
  /**
448
- * Time Complexity: O(n log n)
449
- * Space Complexity: O(n)
450
- *
451
- * Fix the entire heap to maintain heap properties.
516
+ * Deep clone this heap.
517
+ * @remarks Time O(N), Space O(N)
518
+ * @returns A new heap with the same elements.
452
519
  */
453
- fix(): boolean[] {
454
- const results: boolean[] = [];
455
- for (let i = Math.floor(this.size / 2); i >= 0; i--) results.push(this._sinkDown(i, this.elements.length >> 1));
456
- return results;
520
+
521
+ clone(): this {
522
+ const next = this._createInstance();
523
+ for (const x of this.elements) next.add(x);
524
+ return next;
457
525
  }
458
526
 
459
527
  /**
460
- * Time Complexity: O(n)
461
- * Space Complexity: O(n)
462
- *
463
- * The `filter` function creates a new Heap object containing elements that pass a given callback
464
- * function.
465
- * @param callback - The `callback` parameter is a function that will be called for each element in
466
- * the heap. It takes three arguments: the current element, the index of the current element, and the
467
- * heap itself. The callback function should return a boolean value indicating whether the current
468
- * element should be included in the filtered list
469
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
470
- * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
471
- * passed as the `this` value to the `callback` function. If `thisArg` is
472
- * @returns The `filter` method is returning a new `Heap` object that contains the elements that pass
473
- * the filter condition specified by the `callback` function.
474
- */
475
- filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): Heap<E, R> {
476
- const filteredList = new Heap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });
477
- let index = 0;
478
- for (const current of this) {
479
- if (callback.call(thisArg, current, index, this)) {
480
- filteredList.add(current);
528
+ * Filter elements into a new heap of the same class.
529
+ * @remarks Time O(N log N), Space O(N)
530
+ * @param callback - Predicate (element, index, heap) → boolean to keep element.
531
+ * @param [thisArg] - Value for `this` inside the callback.
532
+ * @returns A new heap with the kept elements.
533
+ */
534
+
535
+ filter(callback: ElementCallback<E, R, boolean>, thisArg?: unknown): this {
536
+ const out = this._createInstance();
537
+ let i = 0;
538
+ for (const x of this) {
539
+ if (thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this)) {
540
+ out.add(x);
541
+ } else {
542
+ i++;
481
543
  }
482
- index++;
483
544
  }
484
- return filteredList;
485
- }
486
-
487
- /**
488
- * Time Complexity: O(n)
489
- * Space Complexity: O(n)
490
- *
491
- * The `map` function creates a new heap by applying a callback function to each element of the
492
- * original heap.
493
- * @param callback - The `callback` parameter is a function that will be called for each element in
494
- * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current
495
- * element), and `this` (the heap itself). The callback function should return a value of
496
- * @param comparator - The `comparator` parameter is a function that defines the order of the
497
- * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number
498
- * if `a` should be placed before `b`, a positive number if `a` should be placed after
499
- * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw
500
- * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and
501
- * returns a value of type `T`. This function is used to transform the elements of the original
502
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
503
- * specify the value of `this` within the callback function. It is used to set the context or scope
504
- * in which the callback function will be executed. If `thisArg` is provided, it will be used as the
505
- * value of
506
- * @returns a new instance of the `Heap` class with the mapped elements.
545
+ return out;
546
+ }
547
+
548
+ /**
549
+ * Map elements into a new heap of possibly different element type.
550
+ * @remarks Time O(N log N), Space O(N)
551
+ * @template EM
552
+ * @template RM
553
+ * @param callback - Mapping function (element, index, heap) → newElement.
554
+ * @param options - Options for the output heap, including comparator for EM.
555
+ * @param [thisArg] - Value for `this` inside the callback.
556
+ * @returns A new heap with mapped elements.
507
557
  */
558
+
508
559
  map<EM, RM>(
509
560
  callback: ElementCallback<E, R, EM>,
510
- comparator: Comparator<EM>,
511
- toElementFn?: (rawElement: RM) => EM,
512
- thisArg?: any
561
+ options: HeapOptions<EM, RM> & { comparator: Comparator<EM> },
562
+ thisArg?: unknown
513
563
  ): Heap<EM, RM> {
514
- const mappedHeap: Heap<EM, RM> = new Heap<EM, RM>([], { comparator, toElementFn });
515
- let index = 0;
516
- for (const el of this) {
517
- mappedHeap.add(callback.call(thisArg, el, index, this));
518
- index++;
564
+ const { comparator, toElementFn, ...rest } = options ?? {};
565
+ if (!comparator) throw new TypeError('Heap.map requires options.comparator for EM');
566
+ const out = this._createLike<EM, RM>([], { ...rest, comparator, toElementFn });
567
+ let i = 0;
568
+ for (const x of this) {
569
+ const v = thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
570
+ out.add(v);
519
571
  }
520
- return mappedHeap;
572
+ return out;
573
+ }
574
+
575
+ /**
576
+ * Map elements into a new heap of the same element type.
577
+ * @remarks Time O(N log N), Space O(N)
578
+ * @param callback - Mapping function (element, index, heap) → element.
579
+ * @param [thisArg] - Value for `this` inside the callback.
580
+ * @returns A new heap with mapped elements.
581
+ */
582
+
583
+ mapSame(callback: ElementCallback<E, R, E>, thisArg?: unknown): this {
584
+ const out = this._createInstance();
585
+ let i = 0;
586
+ for (const x of this) {
587
+ const v = thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
588
+ out.add(v);
589
+ }
590
+ return out;
521
591
  }
522
592
 
523
593
  protected _DEFAULT_COMPARATOR = (a: E, b: E): number => {
524
594
  if (typeof a === 'object' || typeof b === 'object') {
525
- throw TypeError(
526
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
527
- );
595
+ throw TypeError('When comparing object types, define a custom comparator in options.');
528
596
  }
529
- if (a > b) return 1;
530
- if (a < b) return -1;
597
+ if ((a as unknown as number) > (b as unknown as number)) return 1;
598
+ if ((a as unknown as number) < (b as unknown as number)) return -1;
531
599
  return 0;
532
600
  };
533
601
 
534
- protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR;
535
-
602
+ protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR; /**
603
+ * Get the comparator used to order elements.
604
+ * @remarks Time O(1), Space O(1)
605
+ * @returns Comparator function.
606
+ */
536
607
  /**
537
- * The function returns the value of the _comparator property.
538
- * @returns The `_comparator` property is being returned.
608
+ * Get the comparator used to order elements.
609
+ * @remarks Time O(1), Space O(1)
610
+ * @returns Comparator function.
539
611
  */
612
+
540
613
  get comparator() {
541
614
  return this._comparator;
542
615
  }
543
616
 
544
- /**
545
- * The function `_getIterator` returns an iterable iterator for the elements in the class.
546
- */
547
617
  protected *_getIterator(): IterableIterator<E> {
548
- for (const element of this.elements) {
549
- yield element;
550
- }
618
+ for (const element of this.elements) yield element;
551
619
  }
552
620
 
553
- /**
554
- * Time Complexity: O(log n)
555
- * Space Complexity: O(1)
556
- *
557
- * Float operation to maintain heap properties after adding an element.
558
- * @param index - The index of the newly added element.
559
- */
560
621
  protected _bubbleUp(index: number): boolean {
561
622
  const element = this.elements[index];
562
623
  while (index > 0) {
@@ -570,14 +631,6 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
570
631
  return true;
571
632
  }
572
633
 
573
- /**
574
- * Time Complexity: O(log n)
575
- * Space Complexity: O(1)
576
- *
577
- * Sinking operation to maintain heap properties after removing the top element.
578
- * @param index - The index from which to start sinking.
579
- * @param halfLength
580
- */
581
634
  protected _sinkDown(index: number, halfLength: number): boolean {
582
635
  const element = this.elements[index];
583
636
  while (index < halfLength) {
@@ -595,8 +648,57 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
595
648
  this.elements[index] = element;
596
649
  return true;
597
650
  }
651
+
652
+ /**
653
+ * (Protected) Create an empty instance of the same concrete class.
654
+ * @remarks Time O(1), Space O(1)
655
+ * @param [options] - Options to override comparator or toElementFn.
656
+ * @returns A like-kind empty heap instance.
657
+ */
658
+
659
+ protected _createInstance(options?: HeapOptions<E, R>): this {
660
+ const Ctor: any = this.constructor;
661
+ const next: any = new Ctor([], { comparator: this.comparator, toElementFn: this.toElementFn, ...(options ?? {}) });
662
+ return next as this;
663
+ }
664
+
665
+ /**
666
+ * (Protected) Create a like-kind instance seeded by elements.
667
+ * @remarks Time O(N log N), Space O(N)
668
+ * @template EM
669
+ * @template RM
670
+ * @param [elements] - Iterable of elements or raw values to seed.
671
+ * @param [options] - Options forwarded to the constructor.
672
+ * @returns A like-kind heap instance.
673
+ */
674
+
675
+ protected _createLike<EM, RM>(
676
+ elements: Iterable<EM> | Iterable<RM> = [],
677
+ options?: HeapOptions<EM, RM>
678
+ ): Heap<EM, RM> {
679
+ const Ctor: any = this.constructor;
680
+ return new Ctor(elements, options) as Heap<EM, RM>;
681
+ }
682
+
683
+ /**
684
+ * (Protected) Spawn an empty like-kind heap instance.
685
+ * @remarks Time O(1), Space O(1)
686
+ * @template EM
687
+ * @template RM
688
+ * @param [options] - Options forwarded to the constructor.
689
+ * @returns An empty like-kind heap instance.
690
+ */
691
+
692
+ protected _spawnLike<EM, RM>(options?: HeapOptions<EM, RM>): Heap<EM, RM> {
693
+ return this._createLike<EM, RM>([], options);
694
+ }
598
695
  }
599
696
 
697
+ /**
698
+ * Node container used by FibonacciHeap.
699
+ * @remarks Time O(1), Space O(1)
700
+ * @template E
701
+ */
600
702
  export class FibonacciHeapNode<E> {
601
703
  element: E;
602
704
  degree: number;
@@ -606,16 +708,6 @@ export class FibonacciHeapNode<E> {
606
708
  parent?: FibonacciHeapNode<E>;
607
709
  marked: boolean;
608
710
 
609
- /**
610
- * The constructor function initializes an object with an element and a degree, and sets the marked
611
- * property to false.
612
- * @param {E} element - The "element" parameter represents the value or data that will be stored in
613
- * the node of a data structure. It can be any type of data, such as a number, string, object, or
614
- * even another data structure.
615
- * @param [degree=0] - The degree parameter represents the degree of the element in a data structure
616
- * called a Fibonacci heap. The degree of a node is the number of children it has. By default, the
617
- * degree is set to 0 when a new node is created.
618
- */
619
711
  constructor(element: E, degree = 0) {
620
712
  this.element = element;
621
713
  this.degree = degree;
@@ -623,39 +715,39 @@ export class FibonacciHeapNode<E> {
623
715
  }
624
716
  }
625
717
 
718
+ /**
719
+ * Fibonacci heap (min-heap) optimized for fast merges and amortized operations.
720
+ * @remarks Time O(1), Space O(1)
721
+ * @template E
722
+ * @example examples will be generated by unit test
723
+ */
626
724
  export class FibonacciHeap<E> {
627
725
  /**
628
- * The constructor function initializes a FibonacciHeap object with an optional comparator function.
629
- * @param [comparator] - The `comparator` parameter is an optional argument that represents a
630
- * function used to compare elements in the FibonacciHeap. If a comparator function is provided, it
631
- * will be used to determine the order of elements in the heap. If no comparator function is
632
- * provided, a default comparator function will be used.
726
+ * Create a FibonacciHeap.
727
+ * @remarks Time O(1), Space O(1)
728
+ * @param [comparator] - Comparator to order elements (min-heap by default).
729
+ * @returns New FibonacciHeap instance.
633
730
  */
731
+
634
732
  constructor(comparator?: Comparator<E>) {
635
733
  this.clear();
636
734
  this._comparator = comparator || this._defaultComparator;
637
-
638
- if (typeof this.comparator !== 'function') {
639
- throw new Error('FibonacciHeap constructor: given comparator should be a function.');
640
- }
735
+ if (typeof this.comparator !== 'function') throw new Error('FibonacciHeap: comparator must be a function.');
641
736
  }
642
737
 
643
738
  protected _root?: FibonacciHeapNode<E>;
644
739
 
645
740
  /**
646
- * The function returns the root node of a Fibonacci heap.
647
- * @returns The method is returning either a FibonacciHeapNode object or undefined.
741
+ * Get the circular root list head.
742
+ * @remarks Time O(1), Space O(1)
743
+ * @returns Root node or undefined.
648
744
  */
745
+
649
746
  get root(): FibonacciHeapNode<E> | undefined {
650
747
  return this._root;
651
748
  }
652
749
 
653
750
  protected _size = 0;
654
-
655
- /**
656
- * The function returns the size of an object.
657
- * @returns The size of the object, which is a number.
658
- */
659
751
  get size(): number {
660
752
  return this._size;
661
753
  }
@@ -663,120 +755,84 @@ export class FibonacciHeap<E> {
663
755
  protected _min?: FibonacciHeapNode<E>;
664
756
 
665
757
  /**
666
- * The function returns the minimum node in a Fibonacci heap.
667
- * @returns The method is returning the minimum node of the Fibonacci heap, which is of type
668
- * `FibonacciHeapNode<E>`. If there is no minimum node, it will return `undefined`.
758
+ * Get the current minimum node.
759
+ * @remarks Time O(1), Space O(1)
760
+ * @returns Min node or undefined.
669
761
  */
762
+
670
763
  get min(): FibonacciHeapNode<E> | undefined {
671
764
  return this._min;
672
765
  }
673
766
 
674
767
  protected _comparator: Comparator<E>;
675
-
676
- /**
677
- * The function returns the comparator used for comparing elements.
678
- * @returns The `_comparator` property of the object.
679
- */
680
768
  get comparator(): Comparator<E> {
681
769
  return this._comparator;
682
770
  }
683
771
 
684
- /**
685
- * Get the size (number of elements) of the heap.
686
- * @returns {number} The size of the heap. Returns 0 if the heap is empty. Returns -1 if the heap is invalid.
687
- */
688
772
  clear(): void {
689
773
  this._root = undefined;
690
774
  this._min = undefined;
691
775
  this._size = 0;
692
776
  }
693
777
 
694
- /**
695
- * Time Complexity: O(1)
696
- * Space Complexity: O(1)
697
- *
698
- * Insert an element into the heap and maintain the heap properties.
699
- * @param element
700
- * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.
701
- */
702
- add(element: E): FibonacciHeap<E> {
703
- return this.push(element);
778
+ add(element: E): boolean {
779
+ this.push(element);
780
+ return true;
704
781
  }
705
782
 
706
783
  /**
707
- * Time Complexity: O(1)
708
- * Space Complexity: O(1)
709
- *
710
- * Insert an element into the heap and maintain the heap properties.
711
- * @param element
712
- * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.
784
+ * Push an element into the root list.
785
+ * @remarks Time O(1) amortized, Space O(1)
786
+ * @param element - Element to insert.
787
+ * @returns This heap.
713
788
  */
714
- push(element: E): FibonacciHeap<E> {
715
- const node = this.createNode(element);
789
+
790
+ push(element: E): this {
791
+ const node = this._createNode(element);
716
792
  node.left = node;
717
793
  node.right = node;
718
794
  this.mergeWithRoot(node);
719
-
720
- if (!this.min || this.comparator(node.element, this.min.element) <= 0) {
721
- this._min = node;
722
- }
723
-
795
+ if (!this.min || this.comparator(node.element, this.min.element) <= 0) this._min = node;
724
796
  this._size++;
725
797
  return this;
726
798
  }
727
799
 
728
- /**
729
- * Time Complexity: O(1)
730
- * Space Complexity: O(1)
731
- *
732
- * Peek at the top element of the heap without removing it.
733
- * @returns The top element or undefined if the heap is empty.
734
- * @protected
735
- */
736
800
  peek(): E | undefined {
737
801
  return this.min ? this.min.element : undefined;
738
802
  }
739
803
 
740
804
  /**
741
- * Time Complexity: O(n), where n is the number of elements in the linked list.
742
- * Space Complexity: O(1)
743
- *
744
- * Get the size (number of elements) of the heap.
745
- * @param {FibonacciHeapNode<E>} head - The head of the linked list.
746
- * @protected
747
- * @returns FibonacciHeapNode<E>[] - An array containing the elements of the linked list.
805
+ * Collect nodes from a circular doubly linked list starting at head.
806
+ * @remarks Time O(K), Space O(K)
807
+ * @param [head] - Start node of the circular list.
808
+ * @returns Array of nodes from the list.
748
809
  */
810
+
749
811
  consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
750
812
  const elements: FibonacciHeapNode<E>[] = [];
751
813
  if (!head) return elements;
752
-
753
814
  let node: FibonacciHeapNode<E> | undefined = head;
754
- let flag = false;
755
-
815
+ let started = false;
756
816
  while (true) {
757
- if (node === head && flag) break;
758
- else if (node === head) flag = true;
759
-
760
- if (node) {
761
- elements.push(node);
762
- node = node.right;
763
- }
817
+ if (node === head && started) break;
818
+ else if (node === head) started = true;
819
+ elements.push(node!);
820
+ node = node!.right;
764
821
  }
765
-
766
822
  return elements;
767
823
  }
768
824
 
769
825
  /**
770
- * Time Complexity: O(1)
771
- * Space Complexity: O(1)
772
- *
773
- * @param parent
774
- * @param node
826
+ * Insert a node into a parent's child list (circular).
827
+ * @remarks Time O(1), Space O(1)
828
+ * @param parent - Parent node.
829
+ * @param node - Child node to insert.
830
+ * @returns void
775
831
  */
832
+
776
833
  mergeWithChild(parent: FibonacciHeapNode<E>, node: FibonacciHeapNode<E>): void {
777
- if (!parent.child) {
778
- parent.child = node;
779
- } else {
834
+ if (!parent.child) parent.child = node;
835
+ else {
780
836
  node.right = parent.child.right;
781
837
  node.left = parent.child;
782
838
  parent.child.right!.left = node;
@@ -784,27 +840,18 @@ export class FibonacciHeap<E> {
784
840
  }
785
841
  }
786
842
 
787
- /**
788
- * Time Complexity: O(log n)
789
- * Space Complexity: O(1)
790
- *
791
- * Remove and return the top element (the smallest or largest element) from the heap.
792
- * @returns The top element or undefined if the heap is empty.
793
- */
794
843
  poll(): E | undefined {
795
844
  return this.pop();
796
845
  }
797
846
 
798
847
  /**
799
- * Time Complexity: O(log n)
800
- * Space Complexity: O(1)
801
- *
802
- * Remove and return the top element (the smallest or largest element) from the heap.
803
- * @returns The top element or undefined if the heap is empty.
848
+ * Remove and return the minimum element, consolidating the root list.
849
+ * @remarks Time O(log N) amortized, Space O(1)
850
+ * @returns Minimum element or undefined.
804
851
  */
852
+
805
853
  pop(): E | undefined {
806
854
  if (this._size === 0) return undefined;
807
-
808
855
  const z = this.min!;
809
856
  if (z.child) {
810
857
  const elements = this.consumeLinkedList(z.child);
@@ -813,9 +860,7 @@ export class FibonacciHeap<E> {
813
860
  node.parent = undefined;
814
861
  }
815
862
  }
816
-
817
863
  this.removeFromRoot(z);
818
-
819
864
  if (z === z.right) {
820
865
  this._min = undefined;
821
866
  this._root = undefined;
@@ -823,83 +868,55 @@ export class FibonacciHeap<E> {
823
868
  this._min = z.right;
824
869
  this._consolidate();
825
870
  }
826
-
827
871
  this._size--;
828
-
829
872
  return z.element;
830
873
  }
831
874
 
832
875
  /**
833
- * Time Complexity: O(1)
834
- * Space Complexity: O(1)
835
- *
836
- * merge two heaps. The heap that is merged will be cleared. The heap that is merged into will remain.
837
- * @param heapToMerge
876
+ * Meld another heap into this heap.
877
+ * @remarks Time O(1), Space O(1)
878
+ * @param heapToMerge - Another FibonacciHeap to meld into this one.
879
+ * @returns void
838
880
  */
839
- merge(heapToMerge: FibonacciHeap<E>): void {
840
- if (heapToMerge.size === 0) {
841
- return; // Nothing to merge
842
- }
843
881
 
844
- // Merge the root lists of the two heaps
882
+ merge(heapToMerge: FibonacciHeap<E>): void {
883
+ if (heapToMerge.size === 0) return;
845
884
  if (this.root && heapToMerge.root) {
846
- const thisRoot = this.root;
847
- const otherRoot = heapToMerge.root;
848
-
849
- const thisRootRight = thisRoot.right!;
850
- const otherRootLeft = otherRoot.left!;
851
-
885
+ const thisRoot = this.root,
886
+ otherRoot = heapToMerge.root;
887
+ const thisRootRight = thisRoot.right!,
888
+ otherRootLeft = otherRoot.left!;
852
889
  thisRoot.right = otherRoot;
853
890
  otherRoot.left = thisRoot;
854
-
855
891
  thisRootRight.left = otherRootLeft;
856
892
  otherRootLeft.right = thisRootRight;
893
+ } else if (!this.root && heapToMerge.root) {
894
+ this._root = heapToMerge.root;
857
895
  }
858
-
859
- // Update the minimum node
860
896
  if (!this.min || (heapToMerge.min && this.comparator(heapToMerge.min.element, this.min.element) < 0)) {
861
897
  this._min = heapToMerge.min;
862
898
  }
863
-
864
- // Update the size
865
899
  this._size += heapToMerge.size;
866
-
867
- // Clear the heap that was merged
868
900
  heapToMerge.clear();
869
901
  }
870
902
 
871
- /**
872
- * Create a new node.
873
- * @param element
874
- * @protected
875
- */
876
- createNode(element: E): FibonacciHeapNode<E> {
903
+ _createNode(element: E): FibonacciHeapNode<E> {
877
904
  return new FibonacciHeapNode<E>(element);
878
905
  }
879
906
 
880
- /**
881
- * Default comparator function used by the heap.
882
- * @param {E} a
883
- * @param {E} b
884
- * @protected
885
- */
907
+ isEmpty(): boolean {
908
+ return this._size === 0;
909
+ }
910
+
886
911
  protected _defaultComparator(a: E, b: E): number {
887
912
  if (a < b) return -1;
888
913
  if (a > b) return 1;
889
914
  return 0;
890
915
  }
891
916
 
892
- /**
893
- * Time Complexity: O(1)
894
- * Space Complexity: O(1)
895
- *
896
- * Merge the given node with the root list.
897
- * @param node - The node to be merged.
898
- */
899
917
  protected mergeWithRoot(node: FibonacciHeapNode<E>): void {
900
- if (!this.root) {
901
- this._root = node;
902
- } else {
918
+ if (!this.root) this._root = node;
919
+ else {
903
920
  node.right = this.root.right;
904
921
  node.left = this.root;
905
922
  this.root.right!.left = node;
@@ -907,29 +924,12 @@ export class FibonacciHeap<E> {
907
924
  }
908
925
  }
909
926
 
910
- /**
911
- * Time Complexity: O(1)
912
- * Space Complexity: O(1)
913
- *
914
- * Remove and return the top element (the smallest or largest element) from the heap.
915
- * @param node - The node to be removed.
916
- * @protected
917
- */
918
927
  protected removeFromRoot(node: FibonacciHeapNode<E>): void {
919
928
  if (this.root === node) this._root = node.right;
920
929
  if (node.left) node.left.right = node.right;
921
930
  if (node.right) node.right.left = node.left;
922
931
  }
923
932
 
924
- /**
925
- * Time Complexity: O(1)
926
- * Space Complexity: O(1)
927
- *
928
- * Remove and return the top element (the smallest or largest element) from the heap.
929
- * @param y
930
- * @param x
931
- * @protected
932
- */
933
933
  protected _link(y: FibonacciHeapNode<E>, x: FibonacciHeapNode<E>): void {
934
934
  this.removeFromRoot(y);
935
935
  y.left = y;
@@ -939,13 +939,6 @@ export class FibonacciHeap<E> {
939
939
  y.parent = x;
940
940
  }
941
941
 
942
- /**
943
- * Time Complexity: O(n log n)
944
- * Space Complexity: O(n)
945
- *
946
- * Remove and return the top element (the smallest or largest element) from the heap.
947
- * @protected
948
- */
949
942
  protected _consolidate(): void {
950
943
  const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this._size);
951
944
  const elements = this.consumeLinkedList(this.root);
@@ -957,28 +950,22 @@ export class FibonacciHeap<E> {
957
950
  for (const node of elements) {
958
951
  x = node;
959
952
  d = x.degree;
960
-
961
953
  while (A[d]) {
962
954
  y = A[d] as FibonacciHeapNode<E>;
963
-
964
955
  if (this.comparator(x.element, y.element) > 0) {
965
956
  t = x;
966
957
  x = y;
967
958
  y = t;
968
959
  }
969
-
970
960
  this._link(y, x);
971
961
  A[d] = undefined;
972
962
  d++;
973
963
  }
974
-
975
964
  A[d] = x;
976
965
  }
977
966
 
978
- for (let i = 0; i < this._size; i++) {
979
- if (A[i] && this.comparator(A[i]!.element, this.min!.element) <= 0) {
980
- this._min = A[i]!;
981
- }
967
+ for (let i = 0; i < A.length; i++) {
968
+ if (A[i] && (!this.min || this.comparator(A[i]!.element, this.min.element) <= 0)) this._min = A[i]!;
982
969
  }
983
970
  }
984
971
  }