undirected-graph-typed 1.54.3 → 2.0.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 (67) hide show
  1. package/dist/data-structures/base/iterable-element-base.d.ts +14 -40
  2. package/dist/data-structures/base/iterable-element-base.js +14 -11
  3. package/dist/data-structures/base/linear-base.d.ts +277 -0
  4. package/dist/data-structures/base/linear-base.js +552 -0
  5. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +12 -8
  6. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +50 -37
  7. package/dist/data-structures/binary-tree/avl-tree.d.ts +64 -0
  8. package/dist/data-structures/binary-tree/avl-tree.js +64 -0
  9. package/dist/data-structures/binary-tree/binary-tree.js +5 -5
  10. package/dist/data-structures/binary-tree/bst.js +11 -11
  11. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +175 -14
  12. package/dist/data-structures/binary-tree/tree-multi-map.js +210 -40
  13. package/dist/data-structures/graph/abstract-graph.js +2 -2
  14. package/dist/data-structures/heap/heap.d.ts +3 -11
  15. package/dist/data-structures/heap/heap.js +0 -10
  16. package/dist/data-structures/heap/max-heap.d.ts +2 -2
  17. package/dist/data-structures/heap/min-heap.d.ts +2 -2
  18. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +65 -94
  19. package/dist/data-structures/linked-list/doubly-linked-list.js +131 -146
  20. package/dist/data-structures/linked-list/singly-linked-list.d.ts +79 -75
  21. package/dist/data-structures/linked-list/singly-linked-list.js +217 -169
  22. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +2 -2
  23. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +2 -2
  24. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -2
  25. package/dist/data-structures/queue/deque.d.ts +130 -91
  26. package/dist/data-structures/queue/deque.js +269 -169
  27. package/dist/data-structures/queue/queue.d.ts +84 -40
  28. package/dist/data-structures/queue/queue.js +134 -50
  29. package/dist/data-structures/stack/stack.d.ts +3 -11
  30. package/dist/data-structures/stack/stack.js +0 -10
  31. package/dist/data-structures/trie/trie.d.ts +4 -3
  32. package/dist/data-structures/trie/trie.js +3 -0
  33. package/dist/types/data-structures/base/base.d.ts +9 -4
  34. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
  35. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
  36. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -2
  37. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +2 -2
  38. package/dist/types/data-structures/queue/deque.d.ts +2 -3
  39. package/dist/types/data-structures/queue/queue.d.ts +2 -2
  40. package/package.json +2 -2
  41. package/src/data-structures/base/iterable-element-base.ts +29 -20
  42. package/src/data-structures/base/linear-base.ts +649 -0
  43. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +51 -36
  44. package/src/data-structures/binary-tree/avl-tree.ts +64 -0
  45. package/src/data-structures/binary-tree/binary-tree.ts +5 -5
  46. package/src/data-structures/binary-tree/bst.ts +9 -9
  47. package/src/data-structures/binary-tree/tree-multi-map.ts +214 -40
  48. package/src/data-structures/graph/abstract-graph.ts +2 -2
  49. package/src/data-structures/heap/heap.ts +3 -14
  50. package/src/data-structures/heap/max-heap.ts +2 -2
  51. package/src/data-structures/heap/min-heap.ts +2 -2
  52. package/src/data-structures/linked-list/doubly-linked-list.ts +144 -160
  53. package/src/data-structures/linked-list/singly-linked-list.ts +241 -185
  54. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -5
  55. package/src/data-structures/priority-queue/min-priority-queue.ts +2 -5
  56. package/src/data-structures/priority-queue/priority-queue.ts +2 -2
  57. package/src/data-structures/queue/deque.ts +286 -183
  58. package/src/data-structures/queue/queue.ts +149 -63
  59. package/src/data-structures/stack/stack.ts +3 -18
  60. package/src/data-structures/trie/trie.ts +7 -3
  61. package/src/types/data-structures/base/base.ts +17 -8
  62. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
  63. package/src/types/data-structures/binary-tree/tree-multi-map.ts +1 -1
  64. package/src/types/data-structures/linked-list/doubly-linked-list.ts +2 -2
  65. package/src/types/data-structures/linked-list/singly-linked-list.ts +2 -2
  66. package/src/types/data-structures/queue/deque.ts +2 -3
  67. package/src/types/data-structures/queue/queue.ts +2 -2
@@ -6,117 +6,76 @@
6
6
  * @license MIT License
7
7
  */
8
8
  import type { ElementCallback, SinglyLinkedListOptions } from '../../types';
9
- import { IterableElementBase } from '../base';
9
+ import { LinearLinkedBase, LinkedListNode } from '../base/linear-base';
10
10
 
11
- export class SinglyLinkedListNode<E = any> {
11
+ export class SinglyLinkedListNode<E = any> extends LinkedListNode<E> {
12
12
  /**
13
13
  * The constructor function initializes an instance of a class with a given value and sets the next property to undefined.
14
14
  * @param {E} value - The "value" parameter is of type E, which means it can be any data type. It represents the value that
15
15
  * will be stored in the node of a linked list.
16
16
  */
17
17
  constructor(value: E) {
18
+ super(value);
18
19
  this._value = value;
19
20
  this._next = undefined;
20
21
  }
21
22
 
22
- protected _value: E;
23
+ protected override _next: SinglyLinkedListNode<E> | undefined;
23
24
 
24
- /**
25
- * The function returns the value of a protected variable.
26
- * @returns The value of the variable `_value` is being returned.
27
- */
28
- get value(): E {
29
- return this._value;
30
- }
31
-
32
- /**
33
- * The above function sets the value of a variable.
34
- * @param {E} value - The parameter "value" is of type E, which means it can be any type.
35
- */
36
- set value(value: E) {
37
- this._value = value;
38
- }
39
-
40
- protected _next: SinglyLinkedListNode<E> | undefined;
41
-
42
- /**
43
- * The `next` function returns the next node in a singly linked list.
44
- * @returns The `next` property is being returned. It can be either a `SinglyLinkedListNode<E>`
45
- * object or `undefined`.
46
- */
47
- get next(): SinglyLinkedListNode<E> | undefined {
25
+ override get next(): SinglyLinkedListNode<E> | undefined {
48
26
  return this._next;
49
27
  }
50
28
 
51
- /**
52
- * The "next" property of a SinglyLinkedListNode is set to the provided value.
53
- * @param {SinglyLinkedListNode<E> | undefined} value - The `value` parameter is of type
54
- * `SinglyLinkedListNode<E> | undefined`. This means that it can accept either a
55
- * `SinglyLinkedListNode` object or `undefined` as its value.
56
- */
57
- set next(value: SinglyLinkedListNode<E> | undefined) {
29
+ override set next(value: SinglyLinkedListNode<E> | undefined) {
58
30
  this._next = value;
59
31
  }
60
32
  }
61
33
 
62
34
  /**
35
+ * 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.
36
+ * 2. Bidirectional Traversal: Unlike doubly linked lists, singly linked lists can be easily traversed forwards but not backwards.
37
+ * 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.
38
+ * 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.
39
+ * Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).
63
40
  *
64
41
  */
65
- export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R, SinglyLinkedList<E, R>> {
42
+ export class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> {
66
43
  constructor(
67
44
  elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>> = [],
68
45
  options?: SinglyLinkedListOptions<E, R>
69
46
  ) {
70
47
  super(options);
48
+
49
+ if (options) {
50
+ }
51
+
71
52
  this.pushMany(elements);
72
53
  }
73
54
 
74
55
  protected _head: SinglyLinkedListNode<E> | undefined;
75
56
 
76
- /**
77
- * The `head` function returns the first node of a singly linked list.
78
- * @returns The method is returning either a SinglyLinkedListNode object or undefined.
79
- */
80
57
  get head(): SinglyLinkedListNode<E> | undefined {
81
58
  return this._head;
82
59
  }
83
60
 
84
61
  protected _tail: SinglyLinkedListNode<E> | undefined;
85
62
 
86
- /**
87
- * The `tail` function returns the last node of a singly linked list.
88
- * @returns The method is returning either a SinglyLinkedListNode object or undefined.
89
- */
90
63
  get tail(): SinglyLinkedListNode<E> | undefined {
91
64
  return this._tail;
92
65
  }
93
66
 
94
- /**
95
- * The above function returns the value of the first element in a linked list, or undefined if the
96
- * list is empty.
97
- * @returns The value of the first node in the linked list, or undefined if the linked list is empty.
98
- */
99
67
  get first(): E | undefined {
100
68
  return this.head?.value;
101
69
  }
102
70
 
103
- /**
104
- * The function returns the value of the last element in a linked list, or undefined if the list is
105
- * empty.
106
- * @returns The value of the last node in the linked list, or undefined if the linked list is empty.
107
- */
108
71
  get last(): E | undefined {
109
72
  return this.tail?.value;
110
73
  }
111
74
 
112
- protected _size: number = 0;
75
+ protected _length: number = 0;
113
76
 
114
- /**
115
- * The function returns the size of an object.
116
- * @returns The size of the object, which is a number.
117
- */
118
- get size(): number {
119
- return this._size;
77
+ get length(): number {
78
+ return this._length;
120
79
  }
121
80
 
122
81
  /**
@@ -154,7 +113,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
154
113
  this.tail!.next = newNode;
155
114
  this._tail = newNode;
156
115
  }
157
- this._size++;
116
+ this._length++;
117
+ if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
158
118
  return true;
159
119
  }
160
120
 
@@ -172,7 +132,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
172
132
  const value = this.head.value;
173
133
  this._head = undefined;
174
134
  this._tail = undefined;
175
- this._size--;
135
+ this._length--;
176
136
  return value;
177
137
  }
178
138
 
@@ -183,7 +143,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
183
143
  const value = this.tail!.value;
184
144
  current.next = undefined;
185
145
  this._tail = current;
186
- this._size--;
146
+ this._length--;
187
147
  return value;
188
148
  }
189
149
 
@@ -198,7 +158,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
198
158
  if (!this.head) return undefined;
199
159
  const removedNode = this.head;
200
160
  this._head = this.head.next;
201
- this._size--;
161
+ this._length--;
202
162
  return removedNode.value;
203
163
  }
204
164
 
@@ -222,7 +182,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
222
182
  newNode.next = this.head;
223
183
  this._head = newNode;
224
184
  }
225
- this._size++;
185
+ this._length++;
226
186
  return true;
227
187
  }
228
188
 
@@ -310,7 +270,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
310
270
  * `undefined` if the index is out of bounds.
311
271
  */
312
272
  at(index: number): E | undefined {
313
- if (index < 0 || index >= this._size) return undefined;
273
+ if (index < 0 || index >= this._length) return undefined;
314
274
  let current = this.head;
315
275
  for (let i = 0; i < index; i++) {
316
276
  current = current!.next;
@@ -365,22 +325,27 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
365
325
  * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
366
326
  * bounds.
367
327
  */
368
- deleteAt(index: number): boolean {
369
- if (index < 0 || index >= this._size) return false;
328
+ deleteAt(index: number): E | undefined {
329
+ if (index < 0 || index >= this._length) return;
330
+ let deleted: E | undefined;
370
331
  if (index === 0) {
332
+ deleted = this.first;
371
333
  this.shift();
372
- return true;
334
+ return deleted;
373
335
  }
374
- if (index === this._size - 1) {
375
- this.pop();
376
- return true;
336
+
337
+ const targetNode = this.getNodeAt(index);
338
+ const prevNode = this._getPrevNode(targetNode!);
339
+
340
+ if (prevNode && targetNode) {
341
+ deleted = targetNode.value;
342
+ prevNode.next = targetNode.next;
343
+ if (targetNode === this.tail) this._tail = prevNode;
344
+ this._length--;
345
+ return deleted;
377
346
  }
378
347
 
379
- const prevNode = this.getNodeAt(index - 1);
380
- const removedNode = prevNode!.next;
381
- prevNode!.next = removedNode!.next;
382
- this._size--;
383
- return true;
348
+ return;
384
349
  }
385
350
 
386
351
  /**
@@ -394,37 +359,25 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
394
359
  * successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
395
360
  */
396
361
  delete(elementOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
397
- if (elementOrNode === undefined) return false;
398
- let value: E;
399
- if (elementOrNode instanceof SinglyLinkedListNode) {
400
- value = elementOrNode.value;
401
- } else {
402
- value = elementOrNode;
403
- }
404
- let current = this.head,
405
- prev = undefined;
362
+ if (elementOrNode === undefined || !this.head) return false;
406
363
 
407
- while (current) {
408
- if (current.value === value) {
409
- if (prev === undefined) {
410
- this._head = current.next;
411
- if (current === this.tail) {
412
- this._tail = undefined;
413
- }
414
- } else {
415
- prev.next = current.next;
416
- if (current === this.tail) {
417
- this._tail = prev;
418
- }
419
- }
420
- this._size--;
421
- return true;
422
- }
423
- prev = current;
424
- current = current.next;
364
+ const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
365
+
366
+ if (!node) return false;
367
+
368
+ const prevNode = this._getPrevNode(node);
369
+
370
+ if (!prevNode) {
371
+ // The node is the head
372
+ this._head = node.next;
373
+ if (node === this.tail) this._tail = undefined;
374
+ } else {
375
+ prevNode.next = node.next;
376
+ if (node === this.tail) this._tail = prevNode;
425
377
  }
426
378
 
427
- return false;
379
+ this._length--;
380
+ return true;
428
381
  }
429
382
 
430
383
  /**
@@ -443,13 +396,13 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
443
396
  * successfully added at the specified index, and `false` if the index is out of bounds.
444
397
  */
445
398
  addAt(index: number, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {
446
- if (index < 0 || index > this._size) return false;
399
+ if (index < 0 || index > this._length) return false;
447
400
 
448
401
  if (index === 0) {
449
402
  this.unshift(newElementOrNode);
450
403
  return true;
451
404
  }
452
- if (index === this._size) {
405
+ if (index === this._length) {
453
406
  this.push(newElementOrNode);
454
407
  return true;
455
408
  }
@@ -458,10 +411,33 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
458
411
  const prevNode = this.getNodeAt(index - 1);
459
412
  newNode.next = prevNode!.next;
460
413
  prevNode!.next = newNode;
461
- this._size++;
414
+ this._length++;
462
415
  return true;
463
416
  }
464
417
 
418
+ /**
419
+ * Time Complexity: O(n)
420
+ * Space Complexity: O(1)
421
+ *
422
+ * The function setAt(index, value) updates the value at a specified index in a data structure if the
423
+ * index exists.
424
+ * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
425
+ * data structure where you want to set a new value.
426
+ * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
427
+ * want to set at the specified index in the data structure.
428
+ * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
429
+ * is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index
430
+ * does not exist).
431
+ */
432
+ setAt(index: number, value: E): boolean {
433
+ const node = this.getNodeAt(index);
434
+ if (node) {
435
+ node.value = value;
436
+ return true;
437
+ }
438
+ return false;
439
+ }
440
+
465
441
  /**
466
442
  * Time Complexity: O(1)
467
443
  * Space Complexity: O(1)
@@ -471,7 +447,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
471
447
  * @returns A boolean value indicating whether the length of the object is equal to 0.
472
448
  */
473
449
  isEmpty(): boolean {
474
- return this._size === 0;
450
+ return this._length === 0;
475
451
  }
476
452
 
477
453
  /**
@@ -483,24 +459,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
483
459
  clear(): void {
484
460
  this._head = undefined;
485
461
  this._tail = undefined;
486
- this._size = 0;
487
- }
488
-
489
- /**
490
- * Time Complexity: O(n)
491
- * Space Complexity: O(n)
492
- *
493
- * The `toArray` function converts a linked list into an array.
494
- * @returns The `toArray()` method is returning an array of type `E[]`.
495
- */
496
- toArray(): E[] {
497
- const array: E[] = [];
498
- let current = this.head;
499
- while (current) {
500
- array.push(current.value);
501
- current = current.next;
502
- }
503
- return array;
462
+ this._length = 0;
504
463
  }
505
464
 
506
465
  /**
@@ -528,35 +487,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
528
487
  return this;
529
488
  }
530
489
 
531
- /**
532
- * Time Complexity: O(n)
533
- * Space Complexity: O(1)
534
- *
535
- * The `indexOf` function in TypeScript searches for a specific element or node in a singly linked
536
- * list and returns its index if found.
537
- * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
538
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `indexOf` method can be one
539
- * of the following types:
540
- * @returns The `indexOf` method returns the index of the first occurrence of the element that
541
- * matches the provided predicate in the singly linked list. If no matching element is found, it
542
- * returns -1.
543
- */
544
- indexOf(elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {
545
- const predicate = this._ensurePredicate(elementNodeOrPredicate);
546
- let index = 0;
547
- let current = this.head;
548
-
549
- while (current) {
550
- if (predicate(current)) {
551
- return index;
552
- }
553
- index++;
554
- current = current.next;
555
- }
556
-
557
- return -1;
558
- }
559
-
560
490
  /**
561
491
  * Time Complexity: O(n)
562
492
  * Space Complexity: O(1)
@@ -574,6 +504,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
574
504
  elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined
575
505
  ): SinglyLinkedListNode<E> | undefined {
576
506
  if (elementNodeOrPredicate === undefined) return;
507
+ if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;
577
508
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
578
509
  let current = this.head;
579
510
 
@@ -607,32 +538,22 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
607
538
  existingElementOrNode: E | SinglyLinkedListNode<E>,
608
539
  newElementOrNode: E | SinglyLinkedListNode<E>
609
540
  ): boolean {
610
- if (!this.head) return false;
541
+ const existingNode = this.getNode(existingElementOrNode);
542
+ if (!existingNode) return false;
611
543
 
612
- let existingValue: E;
613
- if (this.isNode(existingElementOrNode)) {
614
- existingValue = existingElementOrNode.value;
615
- } else {
616
- existingValue = existingElementOrNode;
617
- }
618
- if (this.head.value === existingValue) {
619
- this.unshift(newElementOrNode);
620
- return true;
621
- }
544
+ const prevNode = this._getPrevNode(existingNode);
545
+ const newNode = this._ensureNode(newElementOrNode);
622
546
 
623
- let current = this.head;
624
- while (current.next) {
625
- if (current.next.value === existingValue) {
626
- const newNode = this._ensureNode(newElementOrNode);
627
- newNode.next = current.next;
628
- current.next = newNode;
629
- this._size++;
630
- return true;
631
- }
632
- current = current.next;
547
+ if (!prevNode) {
548
+ // Add at the head
549
+ this.unshift(newNode);
550
+ } else {
551
+ prevNode.next = newNode;
552
+ newNode.next = existingNode;
553
+ this._length++;
633
554
  }
634
555
 
635
- return false;
556
+ return true;
636
557
  }
637
558
 
638
559
  /**
@@ -661,13 +582,82 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
661
582
  if (existingNode === this.tail) {
662
583
  this._tail = newNode;
663
584
  }
664
- this._size++;
585
+ this._length++;
665
586
  return true;
666
587
  }
667
588
 
668
589
  return false;
669
590
  }
670
591
 
592
+ /**
593
+ * Time Complexity: O(n)
594
+ * Space Complexity: O(1)
595
+ *
596
+ * The function `splice` in TypeScript overrides the default behavior to remove and insert elements
597
+ * in a singly linked list while handling boundary cases.
598
+ * @param {number} start - The `start` parameter in the `splice` method indicates the index at which
599
+ * to start modifying the list. It specifies the position where elements will be added or removed.
600
+ * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
601
+ * number of elements to remove from the array starting at the specified `start` index. If
602
+ * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new
603
+ * elements can still be inserted at
604
+ * @param {E[]} items - The `items` parameter in the `splice` method represents the elements to be
605
+ * inserted into the list at the specified `start` index. These elements will be inserted in place of
606
+ * the elements that are removed from the list. The `splice` method allows you to add new elements to
607
+ * the list while
608
+ * @returns The `splice` method is returning a `SinglyLinkedList` containing the elements that were
609
+ * removed from the original list during the splice operation.
610
+ */
611
+ override splice(start: number, deleteCount: number = 0, ...items: E[]): this {
612
+ const removedList = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
613
+
614
+ // If `start` is out of range, perform boundary processing
615
+ start = Math.max(0, Math.min(start, this.length));
616
+ deleteCount = Math.max(0, deleteCount);
617
+
618
+ // Find the predecessor node of `start`
619
+ const prevNode = start === 0 ? undefined : this.getNodeAt(start - 1);
620
+ const startNode = prevNode ? prevNode.next : this.head;
621
+
622
+ let current = startNode;
623
+ for (let i = 0; i < deleteCount && current; i++) {
624
+ removedList.push(current.value);
625
+ current = current.next;
626
+ }
627
+
628
+ const nextNode = current;
629
+ let lastInsertedNode: SinglyLinkedListNode<E> | undefined = undefined;
630
+
631
+ for (const item of items) {
632
+ const newNode = this._ensureNode(item);
633
+ if (!lastInsertedNode) {
634
+ if (prevNode) {
635
+ prevNode.next = newNode;
636
+ } else {
637
+ this._head = newNode;
638
+ }
639
+ } else {
640
+ lastInsertedNode.next = newNode;
641
+ }
642
+ lastInsertedNode = newNode;
643
+ }
644
+
645
+ // Connect new node to `nextNode`
646
+ if (lastInsertedNode) {
647
+ lastInsertedNode.next = nextNode;
648
+ } else if (prevNode) {
649
+ prevNode.next = nextNode;
650
+ }
651
+
652
+ // Update tail node and length
653
+ if (!nextNode) {
654
+ this._tail = lastInsertedNode || prevNode;
655
+ }
656
+ this._length += items.length - removedList.length;
657
+
658
+ return removedList as this;
659
+ }
660
+
671
661
  /**
672
662
  * Time Complexity: O(n)
673
663
  * Space Complexity: O(1)
@@ -703,8 +693,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
703
693
  * @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which
704
694
  * is a clone of the original list.
705
695
  */
706
- clone(): SinglyLinkedList<E, R> {
707
- return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn });
696
+ clone(): this {
697
+ return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;
708
698
  }
709
699
 
710
700
  /**
@@ -724,8 +714,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
724
714
  * @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the
725
715
  * elements that pass the filter condition specified by the `callback` function.
726
716
  */
727
- filter(callback: ElementCallback<E, R, boolean, SinglyLinkedList<E, R>>, thisArg?: any): SinglyLinkedList<E, R> {
728
- const filteredList = new SinglyLinkedList<E, R>([], { toElementFn: this.toElementFn });
717
+ filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): SinglyLinkedList<E, R> {
718
+ const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
729
719
  let index = 0;
730
720
  for (const current of this) {
731
721
  if (callback.call(thisArg, current, index, this)) {
@@ -757,11 +747,11 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
757
747
  * @returns a new instance of the `SinglyLinkedList` class with the mapped elements.
758
748
  */
759
749
  map<EM, RM>(
760
- callback: ElementCallback<E, R, EM, SinglyLinkedList<E, R>>,
750
+ callback: ElementCallback<E, R, EM>,
761
751
  toElementFn?: (rawElement: RM) => EM,
762
752
  thisArg?: any
763
753
  ): SinglyLinkedList<EM, RM> {
764
- const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn });
754
+ const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });
765
755
  let index = 0;
766
756
  for (const current of this) {
767
757
  mappedList.push(callback.call(thisArg, current, index, this));
@@ -771,6 +761,20 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
771
761
  return mappedList;
772
762
  }
773
763
 
764
+ /**
765
+ * The function `_createInstance` returns a new instance of `SinglyLinkedList` with the specified
766
+ * options.
767
+ * @param [options] - The `options` parameter in the `_createInstance` method is of type
768
+ * `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`
769
+ * instance being created. It is an optional parameter, meaning it can be omitted when calling the
770
+ * method.
771
+ * @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options
772
+ * is being returned.
773
+ */
774
+ protected override _createInstance(options?: SinglyLinkedListOptions<E, R>): this {
775
+ return new SinglyLinkedList<E, R>([], options) as this;
776
+ }
777
+
774
778
  /**
775
779
  * The function `_getIterator` returns an iterable iterator that yields the values of a linked list.
776
780
  */
@@ -783,6 +787,38 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
783
787
  }
784
788
  }
785
789
 
790
+ /**
791
+ * The function returns an iterator that iterates over the elements of a collection in reverse order.
792
+ */
793
+ protected *_getReverseIterator(): IterableIterator<E> {
794
+ const reversedArr = [...this].reverse();
795
+
796
+ for (const item of reversedArr) {
797
+ yield item;
798
+ }
799
+ }
800
+
801
+ /**
802
+ * The function `_getNodeIterator` returns an iterator that iterates over the nodes of a singly
803
+ * linked list.
804
+ */
805
+ protected *_getNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {
806
+ let current = this.head;
807
+
808
+ while (current) {
809
+ yield current;
810
+ current = current.next;
811
+ }
812
+ }
813
+
814
+ // protected *_getReverseNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {
815
+ // const reversedArr = [...this._getNodeIterator()].reverse();
816
+ //
817
+ // for (const item of reversedArr) {
818
+ // yield item;
819
+ // }
820
+ // }
821
+
786
822
  /**
787
823
  * The _isPredicate function in TypeScript checks if the input is a function that takes a
788
824
  * SinglyLinkedListNode as an argument and returns a boolean.
@@ -831,4 +867,24 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
831
867
 
832
868
  return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;
833
869
  }
870
+
871
+ /**
872
+ * The function `_getPrevNode` returns the node before a given node in a singly linked list.
873
+ * @param node - The `node` parameter in the `_getPrevNode` method is a reference to a node in a
874
+ * singly linked list. The method is used to find the node that comes before the given node in the
875
+ * linked list.
876
+ * @returns The `_getPrevNode` method returns either the previous node of the input node in a singly
877
+ * linked list or `undefined` if the input node is the head of the list or if the input node is not
878
+ * found in the list.
879
+ */
880
+ protected _getPrevNode(node: SinglyLinkedListNode<E>): SinglyLinkedListNode<E> | undefined {
881
+ if (!this.head || this.head === node) return undefined;
882
+
883
+ let current = this.head;
884
+ while (current.next && current.next !== node) {
885
+ current = current.next;
886
+ }
887
+
888
+ return current.next === node ? current : undefined;
889
+ }
834
890
  }
@@ -64,10 +64,7 @@ export class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
64
64
  * @returns The `filter` method is returning a new `MaxPriorityQueue` object that contains the elements that pass
65
65
  * the filter condition specified by the `callback` function.
66
66
  */
67
- override filter(
68
- callback: ElementCallback<E, R, boolean, MaxPriorityQueue<E, R>>,
69
- thisArg?: any
70
- ): MaxPriorityQueue<E, R> {
67
+ override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxPriorityQueue<E, R> {
71
68
  const filteredPriorityQueue = new MaxPriorityQueue<E, R>([], {
72
69
  toElementFn: this.toElementFn,
73
70
  comparator: this.comparator
@@ -104,7 +101,7 @@ export class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
104
101
  * @returns a new instance of the `MaxPriorityQueue` class with the mapped elements.
105
102
  */
106
103
  override map<EM, RM>(
107
- callback: ElementCallback<E, R, EM, MaxPriorityQueue<E, R>>,
104
+ callback: ElementCallback<E, R, EM>,
108
105
  comparator: Comparator<EM>,
109
106
  toElementFn?: (rawElement: RM) => EM,
110
107
  thisArg?: any