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