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,12 +1,25 @@
1
1
  "use strict";
2
+ /**
3
+ * data-structure-typed
4
+ *
5
+ * @author Pablo Zeng
6
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
7
+ * @license MIT License
8
+ */
2
9
  Object.defineProperty(exports, "__esModule", { value: true });
3
10
  exports.DoublyLinkedList = exports.DoublyLinkedListNode = void 0;
4
11
  const linear_base_1 = require("../base/linear-base");
12
+ /**
13
+ * Node of a doubly linked list; stores value and prev/next links.
14
+ * @remarks Time O(1), Space O(1)
15
+ * @template E
16
+ */
5
17
  class DoublyLinkedListNode extends linear_base_1.LinkedListNode {
6
18
  /**
7
- * The constructor function initializes the value, next, and previous properties of an object.
8
- * @param {E} value - The "value" parameter is the value that will be stored in the node. It can be of any data type, as it
9
- * is defined as a generic type "E".
19
+ * Create a node.
20
+ * @remarks Time O(1), Space O(1)
21
+ * @param value - Element value to store.
22
+ * @returns New node instance.
10
23
  */
11
24
  constructor(value) {
12
25
  super(value);
@@ -14,21 +27,47 @@ class DoublyLinkedListNode extends linear_base_1.LinkedListNode {
14
27
  this._next = undefined;
15
28
  this._prev = undefined;
16
29
  }
30
+ /**
31
+ * Get the next node link.
32
+ * @remarks Time O(1), Space O(1)
33
+ * @returns Next node or undefined.
34
+ */
17
35
  get next() {
18
36
  return this._next;
19
37
  }
38
+ /**
39
+ * Set the next node link.
40
+ * @remarks Time O(1), Space O(1)
41
+ * @param value - Next node or undefined.
42
+ * @returns void
43
+ */
20
44
  set next(value) {
21
45
  this._next = value;
22
46
  }
47
+ /**
48
+ * Get the previous node link.
49
+ * @remarks Time O(1), Space O(1)
50
+ * @returns Previous node or undefined.
51
+ */
23
52
  get prev() {
24
53
  return this._prev;
25
54
  }
55
+ /**
56
+ * Set the previous node link.
57
+ * @remarks Time O(1), Space O(1)
58
+ * @param value - Previous node or undefined.
59
+ * @returns void
60
+ */
26
61
  set prev(value) {
27
62
  this._prev = value;
28
63
  }
29
64
  }
30
65
  exports.DoublyLinkedListNode = DoublyLinkedListNode;
31
66
  /**
67
+ * Doubly linked list with O(1) push/pop/unshift/shift and linear scans.
68
+ * @remarks Time O(1), Space O(1)
69
+ * @template E
70
+ * @template R
32
71
  * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.
33
72
  * 2. Bidirectional Traversal: Unlike singly linked lists, doubly linked lists can be easily traversed forwards or backwards. This makes insertions and deletions in the list more flexible and efficient.
34
73
  * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.
@@ -203,6 +242,16 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
203
242
  * this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();
204
243
  * }
205
244
  *
245
+ * // Get the current cache length
246
+ * get length(): number {
247
+ * return this.list.length;
248
+ * }
249
+ *
250
+ * // Check if it is empty
251
+ * get isEmpty(): boolean {
252
+ * return this.list.isEmpty();
253
+ * }
254
+ *
206
255
  * // Get cached value
207
256
  * get(key: K): V | undefined {
208
257
  * const node = this.map.get(key);
@@ -248,12 +297,6 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
248
297
  * }
249
298
  * }
250
299
  *
251
- * // Move the node to the head of the linked list
252
- * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
253
- * this.list.delete(node);
254
- * this.list.unshift(node.value);
255
- * }
256
- *
257
300
  * // Delete specific key
258
301
  * delete(key: K): boolean {
259
302
  * const node = this.map.get(key);
@@ -273,14 +316,10 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
273
316
  * this.map.clear();
274
317
  * }
275
318
  *
276
- * // Get the current cache length
277
- * get length(): number {
278
- * return this.list.length;
279
- * }
280
- *
281
- * // Check if it is empty
282
- * get isEmpty(): boolean {
283
- * return this.list.isEmpty();
319
+ * // Move the node to the head of the linked list
320
+ * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
321
+ * this.list.delete(node);
322
+ * this.list.unshift(node.value);
284
323
  * }
285
324
  * }
286
325
  *
@@ -463,95 +502,92 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
463
502
  */
464
503
  class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
465
504
  /**
466
- * This TypeScript constructor initializes a DoublyLinkedList with optional elements and options.
467
- * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the constructor is an
468
- * iterable collection of elements of type `E` or `R`. It is used to initialize the DoublyLinkedList
469
- * with the elements provided in the iterable. If no elements are provided, the default value is an
470
- * empty iterable.
471
- * @param [options] - The `options` parameter in the constructor is of type
472
- * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
473
- * configuration options to customize the behavior of the DoublyLinkedList.
505
+ * Create a DoublyLinkedList and optionally bulk-insert elements.
506
+ * @remarks Time O(N), Space O(N)
507
+ * @param [elements] - Iterable of elements or nodes (or raw records if toElementFn is provided).
508
+ * @param [options] - Options such as maxLen and toElementFn.
509
+ * @returns New DoublyLinkedList instance.
474
510
  */
475
511
  constructor(elements = [], options) {
476
512
  super(options);
513
+ this._equals = Object.is;
514
+ this._length = 0;
477
515
  this._head = undefined;
478
516
  this._tail = undefined;
479
517
  this._length = 0;
480
- if (options) {
481
- const { maxLen } = options;
482
- if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0)
483
- this._maxLen = maxLen;
518
+ if ((options === null || options === void 0 ? void 0 : options.maxLen) && Number.isInteger(options.maxLen) && options.maxLen > 0) {
519
+ this._maxLen = options.maxLen;
484
520
  }
485
521
  this.pushMany(elements);
486
522
  }
523
+ /**
524
+ * Get the head node.
525
+ * @remarks Time O(1), Space O(1)
526
+ * @returns Head node or undefined.
527
+ */
487
528
  get head() {
488
529
  return this._head;
489
530
  }
531
+ /**
532
+ * Get the tail node.
533
+ * @remarks Time O(1), Space O(1)
534
+ * @returns Tail node or undefined.
535
+ */
490
536
  get tail() {
491
537
  return this._tail;
492
538
  }
539
+ /**
540
+ * Get the number of elements.
541
+ * @remarks Time O(1), Space O(1)
542
+ * @returns Current length.
543
+ */
493
544
  get length() {
494
545
  return this._length;
495
546
  }
496
547
  /**
497
- * Time Complexity: O(1)
498
- * Space Complexity: O(1)
499
- *
500
- * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.
501
- * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.
548
+ * Get the first element value.
549
+ * @remarks Time O(1), Space O(1)
550
+ * @returns First element or undefined.
502
551
  */
503
552
  get first() {
504
553
  var _a;
505
554
  return (_a = this.head) === null || _a === void 0 ? void 0 : _a.value;
506
555
  }
507
556
  /**
508
- * Time Complexity: O(1)
509
- * Space Complexity: O(1)
510
- *
511
- * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.
512
- * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.
557
+ * Get the last element value.
558
+ * @remarks Time O(1), Space O(1)
559
+ * @returns Last element or undefined.
513
560
  */
514
561
  get last() {
515
562
  var _a;
516
563
  return (_a = this.tail) === null || _a === void 0 ? void 0 : _a.value;
517
564
  }
518
565
  /**
519
- * Time Complexity: O(n)
520
- * Space Complexity: O(n)
521
- *
522
- * The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the
523
- * given array.
524
- * @param {E[]} data - The `data` parameter is an array of elements of type `E`.
525
- * @returns The `fromArray` function returns a DoublyLinkedList object.
566
+ * Create a new list from an array of elements.
567
+ * @remarks Time O(N), Space O(N)
568
+ * @template E
569
+ * @template R
570
+ * @param this - The constructor (subclass) to instantiate.
571
+ * @param data - Array of elements to insert.
572
+ * @returns A new list populated with the array's elements.
526
573
  */
527
574
  static fromArray(data) {
528
- return new DoublyLinkedList(data);
575
+ return new this(data);
529
576
  }
530
577
  /**
531
- * Time Complexity: O(1)
532
- * Space Complexity: O(1)
533
- *
534
- * The function `isNode` in TypeScript checks if a given input is an instance of
535
- * `DoublyLinkedListNode`.
536
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
537
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can
538
- * be one of the following types:
539
- * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
540
- * instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
541
- * parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,
542
- * the function returns `false`.
578
+ * Type guard: check whether the input is a DoublyLinkedListNode.
579
+ * @remarks Time O(1), Space O(1)
580
+ * @param elementNodeOrPredicate - Element, node, or predicate.
581
+ * @returns True if the value is a DoublyLinkedListNode.
543
582
  */
544
583
  isNode(elementNodeOrPredicate) {
545
584
  return elementNodeOrPredicate instanceof DoublyLinkedListNode;
546
585
  }
547
586
  /**
548
- * Time Complexity: O(1)
549
- * Space Complexity: O(1)
550
- *
551
- * The `push` function adds a new element or node to the end of a doubly linked list.
552
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
553
- * method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.
554
- * @returns The `push` method is returning a boolean value, specifically `true`.
587
+ * Append an element/node to the tail.
588
+ * @remarks Time O(1), Space O(1)
589
+ * @param elementOrNode - Element or node to append.
590
+ * @returns True when appended.
555
591
  */
556
592
  push(elementOrNode) {
557
593
  const newNode = this._ensureNode(elementOrNode);
@@ -570,58 +606,50 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
570
606
  return true;
571
607
  }
572
608
  /**
573
- * Time Complexity: O(1)
574
- * Space Complexity: O(1)
575
- *
576
- * The `pop()` function removes and returns the value of the last element in a linked list.
577
- * @returns The method is returning the value of the removed node.
609
+ * Remove and return the tail element.
610
+ * @remarks Time O(1), Space O(1)
611
+ * @returns Removed element or undefined.
578
612
  */
579
613
  pop() {
580
614
  if (!this.tail)
581
615
  return undefined;
582
- const removedNode = this.tail;
616
+ const removed = this.tail;
583
617
  if (this.head === this.tail) {
584
618
  this._head = undefined;
585
619
  this._tail = undefined;
586
620
  }
587
621
  else {
588
- this._tail = removedNode.prev;
622
+ this._tail = removed.prev;
589
623
  this.tail.next = undefined;
590
624
  }
591
625
  this._length--;
592
- return removedNode.value;
626
+ return removed.value;
593
627
  }
594
628
  /**
595
- * Time Complexity: O(1)
596
- * Space Complexity: O(1)
597
- *
598
- * The `shift()` function removes and returns the value of the first element in a doubly linked list.
599
- * @returns The value of the removed node.
629
+ * Remove and return the head element.
630
+ * @remarks Time O(1), Space O(1)
631
+ * @returns Removed element or undefined.
600
632
  */
601
633
  shift() {
602
634
  if (!this.head)
603
635
  return undefined;
604
- const removedNode = this.head;
636
+ const removed = this.head;
605
637
  if (this.head === this.tail) {
606
638
  this._head = undefined;
607
639
  this._tail = undefined;
608
640
  }
609
641
  else {
610
- this._head = removedNode.next;
642
+ this._head = removed.next;
611
643
  this.head.prev = undefined;
612
644
  }
613
645
  this._length--;
614
- return removedNode.value;
646
+ return removed.value;
615
647
  }
616
648
  /**
617
- * Time Complexity: O(1)
618
- * Space Complexity: O(1)
619
- *
620
- * The unshift function adds a new element or node to the beginning of a doubly linked list.
621
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
622
- * `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
623
- * element of type `E`.
624
- * @returns The `unshift` method is returning a boolean value, specifically `true`.
649
+ * Prepend an element/node to the head.
650
+ * @remarks Time O(1), Space O(1)
651
+ * @param elementOrNode - Element or node to prepend.
652
+ * @returns True when prepended.
625
653
  */
626
654
  unshift(elementOrNode) {
627
655
  const newNode = this._ensureNode(elementOrNode);
@@ -640,151 +668,114 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
640
668
  return true;
641
669
  }
642
670
  /**
643
- * Time Complexity: O(k)
644
- * Space Complexity: O(k)
645
- *
646
- * The function `pushMany` iterates over elements and pushes them into a data structure, applying a
647
- * transformation function if provided.
648
- * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
649
- * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,
650
- * or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes
651
- * it onto the linked list. If a transformation function `to
652
- * @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate
653
- * the success or failure of pushing each element into the data structure.
671
+ * Append a sequence of elements/nodes.
672
+ * @remarks Time O(N), Space O(1)
673
+ * @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
674
+ * @returns Array of per-element success flags.
654
675
  */
655
676
  pushMany(elements) {
656
677
  const ans = [];
657
678
  for (const el of elements) {
658
- if (this.toElementFn) {
679
+ if (this.toElementFn)
659
680
  ans.push(this.push(this.toElementFn(el)));
660
- continue;
661
- }
662
- ans.push(this.push(el));
681
+ else
682
+ ans.push(this.push(el));
663
683
  }
664
684
  return ans;
665
685
  }
666
686
  /**
667
- * Time Complexity: O(k)
668
- * Space Complexity: O(k)
669
- *
670
- * The function `unshiftMany` iterates through a collection of elements and adds them to the
671
- * beginning of a Doubly Linked List, returning an array of boolean values indicating the success of
672
- * each insertion.
673
- * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
674
- * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,
675
- * `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and
676
- * performs an `unshift` operation on the doubly linked list
677
- * @returns The `unshiftMany` function returns an array of boolean values indicating the success of
678
- * each unshift operation performed on the elements passed as input.
687
+ * Prepend a sequence of elements/nodes.
688
+ * @remarks Time O(N), Space O(1)
689
+ * @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
690
+ * @returns Array of per-element success flags.
679
691
  */
680
692
  unshiftMany(elements) {
681
693
  const ans = [];
682
694
  for (const el of elements) {
683
- if (this.toElementFn) {
695
+ if (this.toElementFn)
684
696
  ans.push(this.unshift(this.toElementFn(el)));
685
- continue;
686
- }
687
- ans.push(this.unshift(el));
697
+ else
698
+ ans.push(this.unshift(el));
688
699
  }
689
700
  return ans;
690
701
  }
691
702
  /**
692
- * Time Complexity: O(n)
693
- * Space Complexity: O(1)
694
- *
695
- * The `at` function returns the value at a specified index in a linked list, or undefined if the index is out of bounds.
696
- * @param {number} index - The index parameter is a number that represents the position of the element we want to
697
- * retrieve from the list.
698
- * @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds
699
- * or the linked list is empty, it will return undefined.
703
+ * Get the element at a given index.
704
+ * @remarks Time O(N), Space O(1)
705
+ * @param index - Zero-based index.
706
+ * @returns Element or undefined.
700
707
  */
701
708
  at(index) {
702
709
  if (index < 0 || index >= this._length)
703
710
  return undefined;
704
711
  let current = this.head;
705
- for (let i = 0; i < index; i++) {
712
+ for (let i = 0; i < index; i++)
706
713
  current = current.next;
707
- }
708
714
  return current.value;
709
715
  }
710
716
  /**
711
- * Time Complexity: O(n)
712
- * Space Complexity: O(1)
713
- *
714
- * The function `getNodeAt` returns the node at a given index in a doubly linked list, or undefined if the index is out of
715
- * range.
716
- * @param {number} index - The `index` parameter is a number that represents the position of the node we want to
717
- * retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.
718
- * @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the
719
- * valid range of the linked list, otherwise it returns `undefined`.
717
+ * Get the node reference at a given index.
718
+ * @remarks Time O(N), Space O(1)
719
+ * @param index - Zero-based index.
720
+ * @returns Node or undefined.
720
721
  */
721
722
  getNodeAt(index) {
722
723
  if (index < 0 || index >= this._length)
723
724
  return undefined;
724
725
  let current = this.head;
725
- for (let i = 0; i < index; i++) {
726
+ for (let i = 0; i < index; i++)
726
727
  current = current.next;
727
- }
728
728
  return current;
729
729
  }
730
730
  /**
731
- * Time Complexity: O(n)
732
- * Space Complexity: O(1)
733
- *
734
- * This TypeScript function searches for a node in a doubly linked list based on a given element node
735
- * or predicate.
736
- * @param {| E
737
- * | DoublyLinkedListNode<E>
738
- * | ((node: DoublyLinkedListNode<E>) => boolean)
739
- * | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a
740
- * node in a doubly linked list based on a given element, node, or predicate function. The
741
- * `elementNodeOrPredicate` parameter can be one of the following:
742
- * @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the
743
- * input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.
744
- * Otherwise, it iterates through the linked list starting from the head node and applies the
745
- * provided predicate function to each node. If a node satisfies the predicate, that node is
746
- * returned. If
731
+ * Find a node by value, reference, or predicate.
732
+ * @remarks Time O(N), Space O(1)
733
+ * @param [elementNodeOrPredicate] - Element, node, or predicate to match.
734
+ * @returns Matching node or undefined.
747
735
  */
748
736
  getNode(elementNodeOrPredicate) {
749
737
  if (elementNodeOrPredicate === undefined)
750
738
  return;
751
- if (this.isNode(elementNodeOrPredicate))
752
- return elementNodeOrPredicate;
739
+ if (this.isNode(elementNodeOrPredicate)) {
740
+ const target = elementNodeOrPredicate;
741
+ let cur = this.head;
742
+ while (cur) {
743
+ if (cur === target)
744
+ return target;
745
+ cur = cur.next;
746
+ }
747
+ const isMatch = (node) => this._equals(node.value, target.value);
748
+ cur = this.head;
749
+ while (cur) {
750
+ if (isMatch(cur))
751
+ return cur;
752
+ cur = cur.next;
753
+ }
754
+ return undefined;
755
+ }
753
756
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
754
757
  let current = this.head;
755
758
  while (current) {
756
- if (predicate(current)) {
759
+ if (predicate(current))
757
760
  return current;
758
- }
759
761
  current = current.next;
760
762
  }
761
763
  return undefined;
762
764
  }
763
765
  /**
764
- * Time Complexity: O(n)
765
- * Space Complexity: O(1)
766
- *
767
- * The `addAt` function inserts a new element or node at a specified index in a doubly linked list.
768
- * @param {number} index - The `index` parameter in the `addAt` method represents the position at
769
- * which you want to add a new element or node in the doubly linked list. It indicates the location
770
- * where the new element or node should be inserted.
771
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
772
- * `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.
773
- * @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was
774
- * successfully added at the specified index, and `false` if the index is out of bounds (less than 0
775
- * or greater than the length of the list).
766
+ * Insert a new element/node at an index, shifting following nodes.
767
+ * @remarks Time O(N), Space O(1)
768
+ * @param index - Zero-based index.
769
+ * @param newElementOrNode - Element or node to insert.
770
+ * @returns True if inserted.
776
771
  */
777
772
  addAt(index, newElementOrNode) {
778
773
  if (index < 0 || index > this._length)
779
774
  return false;
780
- if (index === 0) {
781
- this.unshift(newElementOrNode);
782
- return true;
783
- }
784
- if (index === this._length) {
785
- this.push(newElementOrNode);
786
- return true;
787
- }
775
+ if (index === 0)
776
+ return this.unshift(newElementOrNode);
777
+ if (index === this._length)
778
+ return this.push(newElementOrNode);
788
779
  const newNode = this._ensureNode(newElementOrNode);
789
780
  const prevNode = this.getNodeAt(index - 1);
790
781
  const nextNode = prevNode.next;
@@ -796,179 +787,123 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
796
787
  return true;
797
788
  }
798
789
  /**
799
- * Time Complexity: O(1) or O(n)
800
- * Space Complexity: O(1)
801
- *
802
- * The `addBefore` function in TypeScript adds a new element or node before an existing element or
803
- * node in a doubly linked list.
804
- * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter
805
- * in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.
806
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter
807
- * represents the element or node that you want to add before the `existingElementOrNode` in a doubly
808
- * linked list.
809
- * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
810
- * successfully added before the existing element or node, and `false` if the existing element or
811
- * node was not found.
790
+ * Insert a new element/node before an existing one.
791
+ * @remarks Time O(N), Space O(1)
792
+ * @param existingElementOrNode - Existing element or node.
793
+ * @param newElementOrNode - Element or node to insert.
794
+ * @returns True if inserted.
812
795
  */
813
796
  addBefore(existingElementOrNode, newElementOrNode) {
814
797
  const existingNode = this.isNode(existingElementOrNode)
815
798
  ? existingElementOrNode
816
799
  : this.getNode(existingElementOrNode);
817
- if (existingNode) {
818
- const newNode = this._ensureNode(newElementOrNode);
819
- newNode.prev = existingNode.prev;
820
- if (existingNode.prev) {
821
- existingNode.prev.next = newNode;
822
- }
823
- newNode.next = existingNode;
824
- existingNode.prev = newNode;
825
- if (existingNode === this.head) {
826
- this._head = newNode;
827
- }
828
- this._length++;
829
- return true;
830
- }
831
- return false;
800
+ if (!existingNode)
801
+ return false;
802
+ const newNode = this._ensureNode(newElementOrNode);
803
+ newNode.prev = existingNode.prev;
804
+ if (existingNode.prev)
805
+ existingNode.prev.next = newNode;
806
+ newNode.next = existingNode;
807
+ existingNode.prev = newNode;
808
+ if (existingNode === this.head)
809
+ this._head = newNode;
810
+ this._length++;
811
+ return true;
832
812
  }
833
813
  /**
834
- * Time Complexity: O(1) or O(n)
835
- * Space Complexity: O(1)
836
- *
837
- * The `addAfter` function in TypeScript adds a new element or node after an existing element or node
838
- * in a doubly linked list.
839
- * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
840
- * element or node in the doubly linked list after which you want to add a new element or node.
841
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
842
- * `addAfter` method represents the element or node that you want to add after the existing element
843
- * or node in a doubly linked list. This parameter can be either an element value or a
844
- * `DoublyLinkedListNode` object that you want to insert
845
- * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
846
- * successfully added after the existing element or node, and `false` if the existing element or node
847
- * was not found in the linked list.
814
+ * Insert a new element/node after an existing one.
815
+ * @remarks Time O(N), Space O(1)
816
+ * @param existingElementOrNode - Existing element or node.
817
+ * @param newElementOrNode - Element or node to insert.
818
+ * @returns True if inserted.
848
819
  */
849
820
  addAfter(existingElementOrNode, newElementOrNode) {
850
821
  const existingNode = this.isNode(existingElementOrNode)
851
822
  ? existingElementOrNode
852
823
  : this.getNode(existingElementOrNode);
853
- if (existingNode) {
854
- const newNode = this._ensureNode(newElementOrNode);
855
- newNode.next = existingNode.next;
856
- if (existingNode.next) {
857
- existingNode.next.prev = newNode;
858
- }
859
- newNode.prev = existingNode;
860
- existingNode.next = newNode;
861
- if (existingNode === this.tail) {
862
- this._tail = newNode;
863
- }
864
- this._length++;
865
- return true;
866
- }
867
- return false;
824
+ if (!existingNode)
825
+ return false;
826
+ const newNode = this._ensureNode(newElementOrNode);
827
+ newNode.next = existingNode.next;
828
+ if (existingNode.next)
829
+ existingNode.next.prev = newNode;
830
+ newNode.prev = existingNode;
831
+ existingNode.next = newNode;
832
+ if (existingNode === this.tail)
833
+ this._tail = newNode;
834
+ this._length++;
835
+ return true;
868
836
  }
869
837
  /**
870
- * Time Complexity: O(n)
871
- * Space Complexity: O(1)
872
- *
873
- * The function `setAt` updates the value at a specified index in a data structure if the index
874
- * exists.
875
- * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
876
- * data structure where you want to set a new value.
877
- * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
878
- * want to set at the specified index in the data structure.
879
- * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
880
- * is successfully updated, and `false` if the index is out of bounds.
838
+ * Set the element value at an index.
839
+ * @remarks Time O(N), Space O(1)
840
+ * @param index - Zero-based index.
841
+ * @param value - New value.
842
+ * @returns True if updated.
881
843
  */
882
844
  setAt(index, value) {
883
845
  const node = this.getNodeAt(index);
884
- if (node) {
885
- node.value = value;
886
- return true;
887
- }
888
- return false;
846
+ if (!node)
847
+ return false;
848
+ node.value = value;
849
+ return true;
889
850
  }
890
851
  /**
891
- * Time Complexity: O(n)
892
- * Space Complexity: O(1)
893
- *
894
- * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.
895
- * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the
896
- * data structure. It is of type number.
897
- * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
898
- * bounds.
852
+ * Delete the element at an index.
853
+ * @remarks Time O(N), Space O(1)
854
+ * @param index - Zero-based index.
855
+ * @returns Removed element or undefined.
899
856
  */
900
857
  deleteAt(index) {
901
858
  if (index < 0 || index >= this._length)
902
859
  return;
903
- let deleted;
904
- if (index === 0) {
905
- deleted = this.first;
906
- this.shift();
907
- return deleted;
908
- }
909
- if (index === this._length - 1) {
910
- deleted = this.last;
911
- this.pop();
912
- return deleted;
913
- }
860
+ if (index === 0)
861
+ return this.shift();
862
+ if (index === this._length - 1)
863
+ return this.pop();
914
864
  const removedNode = this.getNodeAt(index);
915
865
  const prevNode = removedNode.prev;
916
866
  const nextNode = removedNode.next;
917
867
  prevNode.next = nextNode;
918
868
  nextNode.prev = prevNode;
919
869
  this._length--;
920
- return removedNode === null || removedNode === void 0 ? void 0 : removedNode.value;
870
+ return removedNode.value;
921
871
  }
922
872
  /**
923
- * Time Complexity: O(1) or O(n)
924
- * Space Complexity: O(1)
925
- *
926
- * The `delete` function removes a specified element or node from a doubly linked list if it exists.
927
- * @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in
928
- * the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it
929
- * can be `undefined`. This parameter is used to identify the node that needs to be deleted from the
930
- * doubly linked list
931
- * @returns The `delete` method returns a boolean value - `true` if the element or node was
932
- * successfully deleted from the doubly linked list, and `false` if the element or node was not found
933
- * in the list.
873
+ * Delete the first match by value/node.
874
+ * @remarks Time O(N), Space O(1)
875
+ * @param [elementOrNode] - Element or node to remove.
876
+ * @returns True if removed.
934
877
  */
935
878
  delete(elementOrNode) {
936
879
  const node = this.getNode(elementOrNode);
937
- if (node) {
938
- if (node === this.head) {
939
- this.shift();
940
- }
941
- else if (node === this.tail) {
942
- this.pop();
943
- }
944
- else {
945
- const prevNode = node.prev;
946
- const nextNode = node.next;
947
- if (prevNode)
948
- prevNode.next = nextNode;
949
- if (nextNode)
950
- nextNode.prev = prevNode;
951
- this._length--;
952
- }
953
- return true;
880
+ if (!node)
881
+ return false;
882
+ if (node === this.head)
883
+ this.shift();
884
+ else if (node === this.tail)
885
+ this.pop();
886
+ else {
887
+ const prevNode = node.prev;
888
+ const nextNode = node.next;
889
+ prevNode.next = nextNode;
890
+ nextNode.prev = prevNode;
891
+ this._length--;
954
892
  }
955
- return false;
893
+ return true;
956
894
  }
957
895
  /**
958
- * Time Complexity: O(1)
959
- * Space Complexity: O(1)
960
- *
961
- * The function checks if a variable has a length greater than zero and returns a boolean value.
962
- * @returns A boolean value is being returned.
896
+ * Check whether the list is empty.
897
+ * @remarks Time O(1), Space O(1)
898
+ * @returns True if length is 0.
963
899
  */
964
900
  isEmpty() {
965
901
  return this._length === 0;
966
902
  }
967
903
  /**
968
- * Time Complexity: O(1)
969
- * Space Complexity: O(1)
970
- *
971
- * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.
904
+ * Remove all nodes and reset length.
905
+ * @remarks Time O(N), Space O(1)
906
+ * @returns void
972
907
  */
973
908
  clear() {
974
909
  this._head = undefined;
@@ -976,16 +911,10 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
976
911
  this._length = 0;
977
912
  }
978
913
  /**
979
- * Time Complexity: O(n)
980
- * Space Complexity: O(1)
981
- *
982
- * This function retrieves an element from a doubly linked list based on a given element
983
- * node or predicate.
984
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
985
- * elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,
986
- * which can be one of the following types:
987
- * @returns The `get` method returns the value of the first node in the doubly linked list that
988
- * satisfies the provided predicate function. If no such node is found, it returns `undefined`.
914
+ * Find the first value matching a predicate scanning forward.
915
+ * @remarks Time O(N), Space O(1)
916
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
917
+ * @returns Matched value or undefined.
989
918
  */
990
919
  search(elementNodeOrPredicate) {
991
920
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
@@ -998,17 +927,10 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
998
927
  return undefined;
999
928
  }
1000
929
  /**
1001
- * Time Complexity: O(n)
1002
- * Space Complexity: O(1)
1003
- *
1004
- * The `getBackward` function searches for a specific element in a doubly linked list starting from
1005
- * the tail and moving backwards.
1006
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1007
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`
1008
- * function can be one of the following types:
1009
- * @returns The `getBackward` method returns the value of the element node that matches the provided
1010
- * predicate when traversing the doubly linked list backwards. If no matching element is found, it
1011
- * returns `undefined`.
930
+ * Find the first value matching a predicate scanning backward.
931
+ * @remarks Time O(N), Space O(1)
932
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
933
+ * @returns Matched value or undefined.
1012
934
  */
1013
935
  getBackward(elementNodeOrPredicate) {
1014
936
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
@@ -1021,10 +943,9 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
1021
943
  return undefined;
1022
944
  }
1023
945
  /**
1024
- * Time Complexity: O(n)
1025
- * Space Complexity: O(1)
1026
- *
1027
- * The `reverse` function reverses the order of the elements in a doubly linked list.
946
+ * Reverse the list in place.
947
+ * @remarks Time O(N), Space O(1)
948
+ * @returns This list.
1028
949
  */
1029
950
  reverse() {
1030
951
  let current = this.head;
@@ -1037,100 +958,134 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
1037
958
  return this;
1038
959
  }
1039
960
  /**
1040
- * Time Complexity: O(n)
1041
- * Space Complexity: O(n)
1042
- *
1043
- * The `clone` function creates a new instance of the `DoublyLinkedList` class with the same values
1044
- * as the original list.
1045
- * @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which
1046
- * is a copy of the original list.
961
+ * Set the equality comparator used to compare values.
962
+ * @remarks Time O(1), Space O(1)
963
+ * @param equals - Equality predicate (a, b) → boolean.
964
+ * @returns This list.
965
+ */
966
+ setEquality(equals) {
967
+ this._equals = equals;
968
+ return this;
969
+ }
970
+ /**
971
+ * Deep clone this list (values are copied by reference).
972
+ * @remarks Time O(N), Space O(N)
973
+ * @returns A new list with the same element sequence.
1047
974
  */
1048
975
  clone() {
1049
- return new DoublyLinkedList(this, { toElementFn: this._toElementFn, maxLen: this._maxLen });
976
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
977
+ for (const v of this)
978
+ out.push(v);
979
+ return out;
1050
980
  }
1051
981
  /**
1052
- * Time Complexity: O(n)
1053
- * Space Complexity: O(n)
1054
- *
1055
- * The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current
1056
- * list and applying a callback function to each element, returning only the elements for which the
1057
- * callback function returns true.
1058
- * @param callback - The `callback` parameter is a function that will be called for each element in
1059
- * the DoublyLinkedList. It takes three arguments: the current element, the index of the current
1060
- * element, and the DoublyLinkedList itself. The callback function should return a boolean value
1061
- * indicating whether the current element should be included
1062
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
1063
- * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
1064
- * passed as the `this` value to the `callback` function. If `thisArg` is
1065
- * @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
1066
- * elements that pass the filter condition specified by the `callback` function.
982
+ * Filter values into a new list of the same class.
983
+ * @remarks Time O(N), Space O(N)
984
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
985
+ * @param [thisArg] - Value for `this` inside the callback.
986
+ * @returns A new list with kept values.
1067
987
  */
1068
988
  filter(callback, thisArg) {
1069
- const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
989
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1070
990
  let index = 0;
1071
- for (const current of this) {
1072
- if (callback.call(thisArg, current, index, this)) {
1073
- filteredList.push(current);
1074
- }
1075
- index++;
1076
- }
1077
- return filteredList;
991
+ for (const v of this)
992
+ if (callback.call(thisArg, v, index++, this))
993
+ out.push(v);
994
+ return out;
1078
995
  }
1079
996
  /**
1080
- * Time Complexity: O(n)
1081
- * Space Complexity: O(n)
1082
- *
1083
- * The `map` function takes a callback function and returns a new DoublyLinkedList with the results
1084
- * of applying the callback to each element in the original list.
1085
- * @param callback - The callback parameter is a function that will be called for each element in the
1086
- * original DoublyLinkedList. It takes three arguments: current (the current element being
1087
- * processed), index (the index of the current element), and this (the original DoublyLinkedList).
1088
- * The callback function should return a value of type
1089
- * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
1090
- * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as
1091
- * input and returns the converted element. If this parameter is not provided, the raw element will
1092
- * be used as is.
1093
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
1094
- * specify the value of `this` within the callback function. It is used to set the context or scope
1095
- * in which the callback function will be executed. If `thisArg` is provided, it will be used as the
1096
- * value of
1097
- * @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
997
+ * Map values into a new list of the same class.
998
+ * @remarks Time O(N), Space O(N)
999
+ * @param callback - Mapping function (value, index, list) → newValue.
1000
+ * @param [thisArg] - Value for `this` inside the callback.
1001
+ * @returns A new list with mapped values.
1098
1002
  */
1099
- map(callback, toElementFn, thisArg) {
1100
- const mappedList = new DoublyLinkedList([], { toElementFn, maxLen: this._maxLen });
1003
+ mapSame(callback, thisArg) {
1004
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1101
1005
  let index = 0;
1102
- for (const current of this) {
1103
- mappedList.push(callback.call(thisArg, current, index, this));
1104
- index++;
1006
+ for (const v of this) {
1007
+ const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
1008
+ out.push(mv);
1105
1009
  }
1106
- return mappedList;
1010
+ return out;
1107
1011
  }
1108
1012
  /**
1109
- * Time Complexity: O(n)
1110
- * Space Complexity: O(1)
1111
- *
1112
- * The function `countOccurrences` iterates through a doubly linked list and counts the occurrences
1113
- * of a specified element or nodes that satisfy a given predicate.
1114
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementOrNode
1115
- * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:
1116
- * @returns The `countOccurrences` method returns the number of occurrences of the specified element,
1117
- * node, or predicate function in the doubly linked list.
1013
+ * Map values into a new list (possibly different element type).
1014
+ * @remarks Time O(N), Space O(N)
1015
+ * @template EM
1016
+ * @template RM
1017
+ * @param callback - Mapping function (value, index, list) newElement.
1018
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1019
+ * @param [thisArg] - Value for `this` inside the callback.
1020
+ * @returns A new DoublyLinkedList with mapped values.
1118
1021
  */
1119
- countOccurrences(elementOrNode) {
1120
- const predicate = this._ensurePredicate(elementOrNode);
1121
- let count = 0;
1122
- let current = this.head;
1123
- while (current) {
1124
- if (predicate(current)) {
1125
- count++;
1126
- }
1127
- current = current.next;
1022
+ map(callback, options, thisArg) {
1023
+ const out = this._createLike([], Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { maxLen: this._maxLen }));
1024
+ let index = 0;
1025
+ for (const v of this)
1026
+ out.push(callback.call(thisArg, v, index++, this));
1027
+ return out;
1028
+ }
1029
+ /**
1030
+ * (Protected) Create or return a node for the given input (node or raw element).
1031
+ * @remarks Time O(1), Space O(1)
1032
+ * @param elementOrNode - Element value or node to normalize.
1033
+ * @returns A DoublyLinkedListNode for the provided input.
1034
+ */
1035
+ _ensureNode(elementOrNode) {
1036
+ if (this.isNode(elementOrNode))
1037
+ return elementOrNode;
1038
+ return new DoublyLinkedListNode(elementOrNode);
1039
+ }
1040
+ /**
1041
+ * (Protected) Normalize input into a predicate over nodes.
1042
+ * @remarks Time O(1), Space O(1)
1043
+ * @param elementNodeOrPredicate - Element, node, or node predicate.
1044
+ * @returns A predicate function taking a node and returning true/false.
1045
+ */
1046
+ _ensurePredicate(elementNodeOrPredicate) {
1047
+ if (this.isNode(elementNodeOrPredicate)) {
1048
+ const target = elementNodeOrPredicate;
1049
+ return (node) => node === target;
1050
+ }
1051
+ if (typeof elementNodeOrPredicate === 'function') {
1052
+ return elementNodeOrPredicate;
1128
1053
  }
1129
- return count;
1054
+ const value = elementNodeOrPredicate;
1055
+ return (node) => this._equals(node.value, value);
1056
+ }
1057
+ /**
1058
+ * (Protected) Get the previous node of a given node.
1059
+ * @remarks Time O(1), Space O(1)
1060
+ * @param node - A node in the list.
1061
+ * @returns Previous node or undefined.
1062
+ */
1063
+ _getPrevNode(node) {
1064
+ return node.prev;
1065
+ }
1066
+ /**
1067
+ * (Protected) Create an empty instance of the same concrete class.
1068
+ * @remarks Time O(1), Space O(1)
1069
+ * @param [options] - Options forwarded to the constructor.
1070
+ * @returns An empty like-kind list instance.
1071
+ */
1072
+ _createInstance(options) {
1073
+ const Ctor = this.constructor;
1074
+ return new Ctor([], options);
1130
1075
  }
1131
1076
  /**
1132
- * The function returns an iterator that iterates over the values of a linked list.
1077
+ * (Protected) Create a like-kind instance and seed it from an iterable.
1078
+ * @remarks Time O(N), Space O(N)
1079
+ * @template EM
1080
+ * @template RM
1081
+ * @param [elements] - Iterable used to seed the new list.
1082
+ * @param [options] - Options forwarded to the constructor.
1083
+ * @returns A like-kind DoublyLinkedList instance.
1133
1084
  */
1085
+ _createLike(elements = [], options) {
1086
+ const Ctor = this.constructor;
1087
+ return new Ctor(elements, options);
1088
+ }
1134
1089
  *_getIterator() {
1135
1090
  let current = this.head;
1136
1091
  while (current) {
@@ -1138,10 +1093,6 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
1138
1093
  current = current.next;
1139
1094
  }
1140
1095
  }
1141
- /**
1142
- * The function returns an iterator that iterates over the elements of a data structure in reverse
1143
- * order.
1144
- */
1145
1096
  *_getReverseIterator() {
1146
1097
  let current = this.tail;
1147
1098
  while (current) {
@@ -1149,10 +1100,6 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
1149
1100
  current = current.prev;
1150
1101
  }
1151
1102
  }
1152
- /**
1153
- * The function returns an iterator that iterates over the nodes of a doubly linked list starting
1154
- * from the head.
1155
- */
1156
1103
  *_getNodeIterator() {
1157
1104
  let current = this.head;
1158
1105
  while (current) {
@@ -1160,78 +1107,5 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
1160
1107
  current = current.next;
1161
1108
  }
1162
1109
  }
1163
- // protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
1164
- // const reversedArr = [...this._getNodeIterator()].reverse();
1165
- //
1166
- // for (const item of reversedArr) {
1167
- // yield item;
1168
- // }
1169
- // }
1170
- /**
1171
- * The function `_isPredicate` checks if the input is a function that takes a `DoublyLinkedListNode`
1172
- * as an argument and returns a boolean.
1173
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1174
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
1175
- * types:
1176
- * @returns The _isPredicate method is returning a boolean value indicating whether the
1177
- * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
1178
- * function, the method will return true, indicating that it is a predicate function.
1179
- */
1180
- _isPredicate(elementNodeOrPredicate) {
1181
- return typeof elementNodeOrPredicate === 'function';
1182
- }
1183
- /**
1184
- * The function `_ensureNode` ensures that the input is a valid node in a doubly linked list.
1185
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either
1186
- * an element of type `E` or a `DoublyLinkedListNode` containing an element of type `E`.
1187
- * @returns If the `elementOrNode` parameter is already a `DoublyLinkedListNode`, it will be returned
1188
- * as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`
1189
- * value and returned.
1190
- */
1191
- _ensureNode(elementOrNode) {
1192
- if (this.isNode(elementOrNode))
1193
- return elementOrNode;
1194
- return new DoublyLinkedListNode(elementOrNode);
1195
- }
1196
- /**
1197
- * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate
1198
- * function, or a value to compare with the node's value.
1199
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1200
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
1201
- * types:
1202
- * @returns A function is being returned that takes a `DoublyLinkedListNode` as a parameter and
1203
- * returns a boolean value based on the conditions specified in the code.
1204
- */
1205
- _ensurePredicate(elementNodeOrPredicate) {
1206
- if (this.isNode(elementNodeOrPredicate))
1207
- return (node) => node === elementNodeOrPredicate;
1208
- if (this._isPredicate(elementNodeOrPredicate))
1209
- return elementNodeOrPredicate;
1210
- return (node) => node.value === elementNodeOrPredicate;
1211
- }
1212
- /**
1213
- * The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified
1214
- * options.
1215
- * @param [options] - The `options` parameter in the `_createInstance` method is of type
1216
- * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
1217
- * configuration options when creating a new instance of the `DoublyLinkedList` class.
1218
- * @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options
1219
- * is being returned, cast as the current class type.
1220
- */
1221
- _createInstance(options) {
1222
- return new DoublyLinkedList([], options);
1223
- }
1224
- /**
1225
- * The function `_getPrevNode` returns the previous node of a given node in a doubly linked list.
1226
- * @param node - The parameter `node` in the `_getPrevNode` method is of type
1227
- * `DoublyLinkedListNode<E>`, which represents a node in a doubly linked list containing an element
1228
- * of type `E`.
1229
- * @returns The `_getPrevNode` method is returning the previous node of the input `node` in a doubly
1230
- * linked list. If the input node has a previous node, it will return that node. Otherwise, it will
1231
- * return `undefined`.
1232
- */
1233
- _getPrevNode(node) {
1234
- return node.prev;
1235
- }
1236
1110
  }
1237
1111
  exports.DoublyLinkedList = DoublyLinkedList;