avl-tree-typed 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/common/index.js +1 -1
  2. package/dist/constants/index.js +1 -1
  3. package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
  4. package/dist/data-structures/base/iterable-element-base.js +149 -107
  5. package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
  6. package/dist/data-structures/base/iterable-entry-base.js +59 -116
  7. package/dist/data-structures/base/linear-base.d.ts +250 -192
  8. package/dist/data-structures/base/linear-base.js +137 -274
  9. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  10. package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
  11. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  12. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  13. package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
  14. package/dist/data-structures/binary-tree/avl-tree.js +208 -195
  15. package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
  16. package/dist/data-structures/binary-tree/binary-tree.js +612 -879
  17. package/dist/data-structures/binary-tree/bst.d.ts +258 -306
  18. package/dist/data-structures/binary-tree/bst.js +505 -481
  19. package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  20. package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
  21. package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
  22. package/dist/data-structures/binary-tree/tree-counter.js +172 -203
  23. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  24. package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
  25. package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
  26. package/dist/data-structures/graph/abstract-graph.js +267 -237
  27. package/dist/data-structures/graph/directed-graph.d.ts +108 -224
  28. package/dist/data-structures/graph/directed-graph.js +146 -233
  29. package/dist/data-structures/graph/map-graph.d.ts +49 -55
  30. package/dist/data-structures/graph/map-graph.js +56 -59
  31. package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
  32. package/dist/data-structures/graph/undirected-graph.js +129 -149
  33. package/dist/data-structures/hash/hash-map.d.ts +164 -338
  34. package/dist/data-structures/hash/hash-map.js +270 -457
  35. package/dist/data-structures/heap/heap.d.ts +214 -289
  36. package/dist/data-structures/heap/heap.js +340 -349
  37. package/dist/data-structures/heap/max-heap.d.ts +11 -47
  38. package/dist/data-structures/heap/max-heap.js +11 -66
  39. package/dist/data-structures/heap/min-heap.d.ts +12 -47
  40. package/dist/data-structures/heap/min-heap.js +11 -66
  41. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  42. package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
  43. package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  44. package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
  45. package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  46. package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
  47. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  48. package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
  49. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  50. package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
  51. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
  52. package/dist/data-structures/priority-queue/priority-queue.js +8 -83
  53. package/dist/data-structures/queue/deque.d.ts +227 -254
  54. package/dist/data-structures/queue/deque.js +309 -348
  55. package/dist/data-structures/queue/queue.d.ts +180 -201
  56. package/dist/data-structures/queue/queue.js +265 -248
  57. package/dist/data-structures/stack/stack.d.ts +124 -102
  58. package/dist/data-structures/stack/stack.js +181 -125
  59. package/dist/data-structures/trie/trie.d.ts +164 -165
  60. package/dist/data-structures/trie/trie.js +189 -172
  61. package/dist/interfaces/binary-tree.d.ts +56 -6
  62. package/dist/interfaces/graph.d.ts +16 -0
  63. package/dist/types/data-structures/base/base.d.ts +1 -1
  64. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
  65. package/dist/types/utils/utils.d.ts +6 -6
  66. package/dist/utils/number.js +1 -2
  67. package/dist/utils/utils.d.ts +110 -49
  68. package/dist/utils/utils.js +149 -74
  69. package/package.json +15 -15
  70. package/src/data-structures/base/iterable-element-base.ts +238 -115
  71. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  72. package/src/data-structures/base/linear-base.ts +271 -277
  73. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  74. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  75. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  76. package/src/data-structures/binary-tree/binary-tree.ts +681 -905
  77. package/src/data-structures/binary-tree/bst.ts +568 -570
  78. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  79. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  80. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  81. package/src/data-structures/graph/abstract-graph.ts +339 -264
  82. package/src/data-structures/graph/directed-graph.ts +146 -236
  83. package/src/data-structures/graph/map-graph.ts +63 -60
  84. package/src/data-structures/graph/undirected-graph.ts +129 -152
  85. package/src/data-structures/hash/hash-map.ts +274 -496
  86. package/src/data-structures/heap/heap.ts +389 -402
  87. package/src/data-structures/heap/max-heap.ts +12 -76
  88. package/src/data-structures/heap/min-heap.ts +13 -76
  89. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  90. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  91. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  92. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  93. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  94. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  95. package/src/data-structures/queue/deque.ts +381 -357
  96. package/src/data-structures/queue/queue.ts +310 -264
  97. package/src/data-structures/stack/stack.ts +217 -131
  98. package/src/data-structures/trie/trie.ts +240 -175
  99. package/src/interfaces/binary-tree.ts +240 -6
  100. package/src/interfaces/graph.ts +37 -0
  101. package/src/types/data-structures/base/base.ts +5 -5
  102. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  103. package/src/types/utils/utils.ts +9 -5
  104. package/src/utils/utils.ts +152 -86
@@ -1,7 +1,17 @@
1
- import { ElementCallback, LinearBaseOptions, ReduceLinearCallback } from '../../types';
1
+ import type { ElementCallback, LinearBaseOptions, ReduceLinearCallback } from '../../types';
2
2
  import { IterableElementBase } from './iterable-element-base';
3
3
 
4
+ /**
5
+ * Singly-linked list node.
6
+ * @template E - Element type.
7
+ * @remarks Time O(1), Space O(1)
8
+ */
4
9
  export class LinkedListNode<E = any> {
10
+ /**
11
+ * Initialize a node.
12
+ * @param value - Element value.
13
+ * @remarks Time O(1), Space O(1)
14
+ */
5
15
  constructor(value: E) {
6
16
  this._value = value;
7
17
  this._next = undefined;
@@ -9,36 +19,61 @@ export class LinkedListNode<E = any> {
9
19
 
10
20
  protected _value: E;
11
21
 
22
+ /**
23
+ * Element payload getter.
24
+ * @returns Element value.
25
+ * @remarks Time O(1), Space O(1)
26
+ */
12
27
  get value(): E {
13
28
  return this._value;
14
29
  }
15
30
 
31
+ /**
32
+ * Element payload setter.
33
+ * @param value - New value.
34
+ * @remarks Time O(1), Space O(1)
35
+ */
16
36
  set value(value: E) {
17
37
  this._value = value;
18
38
  }
19
39
 
20
40
  protected _next: LinkedListNode<E> | undefined;
21
41
 
42
+ /**
43
+ * Next node getter.
44
+ * @returns Next node or `undefined`.
45
+ * @remarks Time O(1), Space O(1)
46
+ */
22
47
  get next(): LinkedListNode<E> | undefined {
23
48
  return this._next;
24
49
  }
25
50
 
51
+ /**
52
+ * Next node setter.
53
+ * @param value - Next node or `undefined`.
54
+ * @remarks Time O(1), Space O(1)
55
+ */
26
56
  set next(value: LinkedListNode<E> | undefined) {
27
57
  this._next = value;
28
58
  }
29
59
  }
30
60
 
61
+ /**
62
+ * Abstract linear container with array-like utilities.
63
+ * @template E - Element type.
64
+ * @template R - Return type for mapped/derived views.
65
+ * @template NODE - Linked node type used by some implementations.
66
+ * @remarks Time O(1), Space O(1)
67
+ */
31
68
  export abstract class LinearBase<
32
69
  E,
33
70
  R = any,
34
71
  NODE extends LinkedListNode<E> = LinkedListNode<E>
35
72
  > extends IterableElementBase<E, R> {
36
73
  /**
37
- * The constructor initializes the LinearBase class with optional options, setting the maximum length
38
- * if provided.
39
- * @param [options] - The `options` parameter is an optional object that can be passed to the
40
- * constructor. It is of type `LinearBaseOptions<E, R>`. The constructor checks if the `options`
41
- * object is provided and then extracts the `maxLen` property from it. If `maxLen` is a
74
+ * Construct a linear container with runtime options.
75
+ * @param options - `{ maxLen?, ... }` bounds/behavior options.
76
+ * @remarks Time O(1), Space O(1)
42
77
  */
43
78
  protected constructor(options?: LinearBaseOptions<E, R>) {
44
79
  super(options);
@@ -48,62 +83,50 @@ export abstract class LinearBase<
48
83
  }
49
84
  }
50
85
 
86
+ /**
87
+ * Element count.
88
+ * @returns Number of elements.
89
+ * @remarks Time O(1), Space O(1)
90
+ */
51
91
  abstract get length(): number;
52
92
 
53
93
  protected _maxLen: number = -1;
54
94
 
95
+ /**
96
+ * Upper bound for length (if positive), or `-1` when unbounded.
97
+ * @returns Maximum allowed length.
98
+ * @remarks Time O(1), Space O(1)
99
+ */
55
100
  get maxLen() {
56
101
  return this._maxLen;
57
102
  }
58
103
 
59
104
  /**
60
- * Time Complexity: O(n)
61
- * Space Complexity: O(1)
62
- *
63
- * The function indexOf searches for a specified element starting from a given index in an array-like
64
- * object and returns the index of the first occurrence, or -1 if not found.
65
- * @param {E} searchElement - The `searchElement` parameter in the `indexOf` function represents the
66
- * element that you want to find within the array. The function will search for this element starting
67
- * from the `fromIndex` (if provided) up to the end of the array. If the `searchElement` is found
68
- * within the
69
- * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` function represents the
70
- * index at which to start searching for the `searchElement` within the array. If provided, the
71
- * search will begin at this index and continue to the end of the array. If `fromIndex` is not
72
- * specified, the default
73
- * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the
74
- * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.
105
+ * First index of a value from the left.
106
+ * @param searchElement - Value to match.
107
+ * @param fromIndex - Start position (supports negative index).
108
+ * @returns Index or `-1` if not found.
109
+ * @remarks Time O(n), Space O(1)
75
110
  */
76
111
  indexOf(searchElement: E, fromIndex: number = 0): number {
77
- // Boundary checks and adjustments
78
112
  if (this.length === 0) return -1;
79
113
  if (fromIndex < 0) fromIndex = this.length + fromIndex;
80
114
  if (fromIndex < 0) fromIndex = 0;
81
115
 
82
- // Iterating from the specified index to the end
83
116
  for (let i = fromIndex; i < this.length; i++) {
84
117
  const element = this.at(i);
85
118
  if (element === searchElement) return i;
86
119
  }
87
120
 
88
- return -1; // Not found
121
+ return -1;
89
122
  }
90
123
 
91
124
  /**
92
- * Time Complexity: O(n)
93
- * Space Complexity: O(1)
94
- *
95
- * The function `lastIndexOf` in TypeScript returns the index of the last occurrence of a specified
96
- * element in an array.
97
- * @param {E} searchElement - The `searchElement` parameter is the element that you want to find the
98
- * last index of within the array. The `lastIndexOf` method will search the array starting from the
99
- * `fromIndex` (or the end of the array if not specified) and return the index of the last occurrence
100
- * of the
101
- * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the
102
- * index at which to start searching for the `searchElement` in the array. By default, it starts
103
- * searching from the last element of the array (`this.length - 1`). If a specific `fromIndex` is
104
- * provided
105
- * @returns The last index of the `searchElement` in the array is being returned. If the
106
- * `searchElement` is not found in the array, -1 is returned.
125
+ * Last index of a value from the right.
126
+ * @param searchElement - Value to match.
127
+ * @param fromIndex - Start position (supports negative index).
128
+ * @returns Index or `-1` if not found.
129
+ * @remarks Time O(n), Space O(1)
107
130
  */
108
131
  lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {
109
132
  if (this.length === 0) return -1;
@@ -119,19 +142,11 @@ export abstract class LinearBase<
119
142
  }
120
143
 
121
144
  /**
122
- * Time Complexity: O(n)
123
- * Space Complexity: O(1)
124
- *
125
- * The `findIndex` function iterates over an array and returns the index of the first element that
126
- * satisfies the provided predicate function.
127
- * @param predicate - The `predicate` parameter in the `findIndex` function is a callback function
128
- * that takes three arguments: `item`, `index`, and the array `this`. It should return a boolean
129
- * value indicating whether the current element satisfies the condition being checked for.
130
- * @param {any} [thisArg] - The `thisArg` parameter in the `findIndex` function is an optional
131
- * parameter that specifies the value to use as `this` when executing the `predicate` function. If
132
- * provided, the `predicate` function will be called with `thisArg` as its `this` value. If `
133
- * @returns The `findIndex` method is returning the index of the first element in the array that
134
- * satisfies the provided predicate function. If no such element is found, it returns -1.
145
+ * Find the first index matching a predicate.
146
+ * @param predicate - `(element, index, self) => boolean`.
147
+ * @param thisArg - Optional `this` for callback.
148
+ * @returns Index or `-1`.
149
+ * @remarks Time O(n), Space O(1)
135
150
  */
136
151
  findIndex(predicate: ElementCallback<E, R, boolean>, thisArg?: any): number {
137
152
  for (let i = 0; i < this.length; i++) {
@@ -141,18 +156,19 @@ export abstract class LinearBase<
141
156
  return -1;
142
157
  }
143
158
 
159
+ /**
160
+ * Concatenate multiple containers of the same species.
161
+ * @param items - Other lists to append.
162
+ * @returns New container with combined elements (`this` type).
163
+ * @remarks Time O(sum(length)), Space O(sum(length))
164
+ */
144
165
  concat(...items: this[]): this;
145
166
 
146
167
  /**
147
- * Time Complexity: O(n + m)
148
- * Space Complexity: O(n + m)
149
- *
150
- * The `concat` function in TypeScript concatenates multiple items into a new list, handling both
151
- * individual elements and instances of `LinearBase`.
152
- * @param {(E | this)[]} items - The `concat` method takes in an array of items, where
153
- * each item can be either of type `E` or an instance of `LinearBase<E, R>`.
154
- * @returns The `concat` method is returning a new instance of the class that it belongs to, with the
155
- * items passed as arguments concatenated to it.
168
+ * Concatenate elements and/or containers.
169
+ * @param items - Elements or other containers.
170
+ * @returns New container with combined elements (`this` type).
171
+ * @remarks Time O(sum(length)), Space O(sum(length))
156
172
  */
157
173
  concat(...items: (E | this)[]): this {
158
174
  const newList = this.clone();
@@ -169,16 +185,10 @@ export abstract class LinearBase<
169
185
  }
170
186
 
171
187
  /**
172
- * Time Complexity: O(n log n)
173
- * Space Complexity: O(n)
174
- *
175
- * The `sort` function in TypeScript sorts the elements of a collection using a specified comparison
176
- * function.
177
- * @param [compareFn] - The `compareFn` parameter is a function that defines the sort order. It takes
178
- * two elements `a` and `b` as input and returns a number indicating their relative order. If the
179
- * returned value is negative, `a` comes before `b`. If the returned value is positive, `
180
- * @returns The `sort` method is returning the instance of the object on which it is called (this),
181
- * after sorting the elements based on the provided comparison function (compareFn).
188
+ * In-place stable order via array sort semantics.
189
+ * @param compareFn - Comparator `(a, b) => number`.
190
+ * @returns This container.
191
+ * @remarks Time O(n log n), Space O(n) (materializes to array temporarily)
182
192
  */
183
193
  sort(compareFn?: (a: E, b: E) => number): this {
184
194
  const arr = this.toArray();
@@ -189,75 +199,48 @@ export abstract class LinearBase<
189
199
  }
190
200
 
191
201
  /**
192
- * Time Complexity: O(n + m)
193
- * Space Complexity: O(m)
194
- *
195
- * The `splice` function in TypeScript removes elements from an array and optionally inserts new
196
- * elements at the specified index.
197
- * @param {number} start - The `start` parameter in the `splice` method indicates the index at which
198
- * to start modifying the array. If `start` is a negative number, it will count from the end of the
199
- * array.
200
- * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
201
- * number of elements to remove from the array starting at the specified `start` index. If
202
- * `deleteCount` is not provided or is 0, no elements are removed, and only new elements are inserted
203
- * at the `start`
204
- * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that
205
- * will be inserted into the array at the specified `start` index. These elements can be of any type
206
- * and you can pass multiple elements separated by commas. The `splice` method will insert these
207
- * items into the array at the
208
- * @returns The `splice` method returns a list of elements that were removed from the original list
209
- * during the operation.
202
+ * Remove and/or insert elements at a position (array-compatible).
203
+ * @param start - Start index (supports negative index).
204
+ * @param deleteCount - How many to remove.
205
+ * @param items - Elements to insert.
206
+ * @returns Removed elements as a new list (`this` type).
207
+ * @remarks Time O(n + m), Space O(min(n, m)) where `m = items.length`
210
208
  */
211
209
  splice(start: number, deleteCount: number = 0, ...items: E[]): this {
212
210
  const removedList = this._createInstance();
213
211
 
214
- // Handling negative indexes and bounds
215
212
  start = start < 0 ? this.length + start : start;
216
213
  start = Math.max(0, Math.min(start, this.length));
217
214
  deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));
218
215
 
219
- // Delete elements
220
216
  for (let i = 0; i < deleteCount; i++) {
221
- const removed = this.deleteAt(start); // Always delete the start position
217
+ const removed = this.deleteAt(start);
222
218
  if (removed !== undefined) {
223
- removedList.push(removed); // Add removed elements to the returned list
219
+ removedList.push(removed);
224
220
  }
225
221
  }
226
222
 
227
- // Insert new element
228
223
  for (let i = 0; i < items.length; i++) {
229
- this.addAt(start + i, items[i]); // Insert new elements one by one at the current position
224
+ this.addAt(start + i, items[i]);
230
225
  }
231
226
 
232
- return removedList; // Returns a list of removed elements
227
+ return removedList;
233
228
  }
234
229
 
235
230
  /**
236
- * Time Complexity: O(n)
237
- * Space Complexity: O(1)
238
- *
239
- * The `join` function in TypeScript returns a string by joining the elements of an array with a
240
- * specified separator.
241
- * @param {string} [separator=,] - The `separator` parameter is a string that specifies the character
242
- * or characters that will be used to separate each element when joining them into a single string.
243
- * By default, the separator is set to a comma (`,`), but you can provide a different separator if
244
- * needed.
245
- * @returns The `join` method is being returned, which takes an optional `separator` parameter
246
- * (defaulting to a comma) and returns a string created by joining all elements of the array after
247
- * converting it to an array.
231
+ * Join all elements into a string.
232
+ * @param separator - Separator string.
233
+ * @returns Concatenated string.
234
+ * @remarks Time O(n), Space O(n)
248
235
  */
249
236
  join(separator: string = ','): string {
250
237
  return this.toArray().join(separator);
251
238
  }
252
239
 
253
240
  /**
254
- * Time Complexity: O(n)
255
- * Space Complexity: O(n)
256
- *
257
- * The function `toReversedArray` takes an array and returns a new array with its elements in reverse
258
- * order.
259
- * @returns The `toReversedArray()` function returns an array of elements of type `E` in reverse
260
- * order.
241
+ * Snapshot elements into a reversed array.
242
+ * @returns New reversed array.
243
+ * @remarks Time O(n), Space O(n)
261
244
  */
262
245
  toReversedArray(): E[] {
263
246
  const array: E[] = [];
@@ -271,23 +254,15 @@ export abstract class LinearBase<
271
254
 
272
255
  reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;
273
256
 
274
- reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
275
-
276
257
  /**
277
- * Time Complexity: O(n)
278
- * Space Complexity: O(1)
279
- *
280
- * The `reduceRight` function in TypeScript iterates over an array from right to left and applies a
281
- * callback function to each element, accumulating a single result.
282
- * @param callbackfn - The `callbackfn` parameter in the `reduceRight` method is a function that will
283
- * be called on each element in the array from right to left. It takes four arguments:
284
- * @param {U} [initialValue] - The `initialValue` parameter in the `reduceRight` method is an
285
- * optional parameter that specifies the initial value of the accumulator. If provided, the
286
- * `accumulator` will start with this initial value before iterating over the elements of the array.
287
- * If `initialValue` is not provided, the accumulator will
288
- * @returns The `reduceRight` method is returning the final accumulated value after applying the
289
- * callback function to each element in the array from right to left.
258
+ * Right-to-left reduction over elements.
259
+ * @param callbackfn - `(acc, element, index, self) => acc`.
260
+ * @param initialValue - Initial accumulator (optional generic overloads supported).
261
+ * @returns Final accumulator.
262
+ * @remarks Time O(n), Space O(1)
290
263
  */
264
+ reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
265
+
291
266
  reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {
292
267
  let accumulator = initialValue ?? (0 as U);
293
268
  for (let i = this.length - 1; i >= 0; i--) {
@@ -297,20 +272,11 @@ export abstract class LinearBase<
297
272
  }
298
273
 
299
274
  /**
300
- * Time Complexity: O(m)
301
- * Space Complexity: O(m)
302
- *
303
- * The `slice` function in TypeScript creates a new instance by extracting a portion of elements from
304
- * the original instance based on the specified start and end indices.
305
- * @param {number} [start=0] - The `start` parameter in the `slice` method represents the index at
306
- * which to begin extracting elements from an array-like object. If no `start` parameter is provided,
307
- * the default value is 0, meaning the extraction will start from the beginning of the array.
308
- * @param {number} end - The `end` parameter in the `slice` method represents the index at which to
309
- * end the slicing. By default, if no `end` parameter is provided, it will slice until the end of the
310
- * array (i.e., `this.length`).
311
- * @returns The `slice` method is returning a new instance of the object with elements sliced from
312
- * the specified start index (default is 0) to the specified end index (default is the length of the
313
- * object).
275
+ * Create a shallow copy of a subrange.
276
+ * @param start - Inclusive start (supports negative index).
277
+ * @param end - Exclusive end (supports negative index).
278
+ * @returns New list with the range (`this` type).
279
+ * @remarks Time O(n), Space O(n)
314
280
  */
315
281
  slice(start: number = 0, end: number = this.length): this {
316
282
  start = start < 0 ? this.length + start : start;
@@ -324,33 +290,21 @@ export abstract class LinearBase<
324
290
  }
325
291
 
326
292
  /**
327
- * Time Complexity: O(n)
328
- * Space Complexity: O(1)
329
- *
330
- * The `fill` function in TypeScript fills a specified range in an array-like object with a given
331
- * value.
332
- * @param {E} value - The `value` parameter in the `fill` method represents the element that will be
333
- * used to fill the specified range in the array.
334
- * @param [start=0] - The `start` parameter specifies the index at which to start filling the array
335
- * with the specified value. If not provided, it defaults to 0, indicating the beginning of the
336
- * array.
337
- * @param end - The `end` parameter in the `fill` function represents the index at which the filling
338
- * of values should stop. It specifies the end of the range within the array where the `value` should
339
- * be filled.
340
- * @returns The `fill` method is returning the modified object (`this`) after filling the specified
341
- * range with the provided value.
293
+ * Fill a range with a value.
294
+ * @param value - Value to set.
295
+ * @param start - Inclusive start.
296
+ * @param end - Exclusive end.
297
+ * @returns This list.
298
+ * @remarks Time O(n), Space O(1)
342
299
  */
343
300
  fill(value: E, start = 0, end = this.length): this {
344
- // Handling negative indexes
345
301
  start = start < 0 ? this.length + start : start;
346
302
  end = end < 0 ? this.length + end : end;
347
303
 
348
- // Boundary processing
349
304
  if (start < 0) start = 0;
350
305
  if (end > this.length) end = this.length;
351
306
  if (start >= end) return this;
352
307
 
353
- // Iterate through the specified range and fill in the values
354
308
  for (let i = start; i < end; i++) {
355
309
  this.setAt(i, value);
356
310
  }
@@ -358,41 +312,106 @@ export abstract class LinearBase<
358
312
  return this;
359
313
  }
360
314
 
315
+ /**
316
+ * Set the value at an index.
317
+ * @param index - Position (0-based).
318
+ * @param value - New value.
319
+ * @returns `true` if updated.
320
+ * @remarks Time O(1) typical, Space O(1)
321
+ */
361
322
  abstract setAt(index: number, value: E): boolean;
362
323
 
324
+ /**
325
+ * Deep clone while preserving concrete subtype.
326
+ * @returns New list of the same species (`this` type).
327
+ * @remarks Time O(n), Space O(n)
328
+ */
363
329
  abstract override clone(): this;
364
330
 
331
+ /**
332
+ * Reverse the order of elements in-place (or equivalent).
333
+ * @returns This list.
334
+ * @remarks Time O(n), Space O(1)
335
+ */
365
336
  abstract reverse(): this;
366
337
 
338
+ /**
339
+ * Append one element or node to the tail.
340
+ * @param elementOrNode - Element or node.
341
+ * @returns `true` if appended.
342
+ * @remarks Time O(1) amortized typical, Space O(1)
343
+ */
367
344
  abstract push(elementOrNode: E | NODE): boolean;
368
345
 
346
+ /**
347
+ * Append many elements/nodes at once.
348
+ * @param elements - Iterable of elements or nodes.
349
+ * @returns Array of booleans indicating append success.
350
+ * @remarks Time O(n), Space O(1)
351
+ */
369
352
  abstract pushMany(elements: Iterable<E> | Iterable<R> | Iterable<NODE>): boolean[];
370
353
 
354
+ /**
355
+ * Remove one element or node if present.
356
+ * @param elementOrNode - Element or node to delete.
357
+ * @returns `true` if removed.
358
+ * @remarks Time O(1)~O(n) depending on implementation, Space O(1)
359
+ */
371
360
  abstract delete(elementOrNode: E | NODE | undefined): boolean;
372
361
 
362
+ /**
363
+ * Get element at an index.
364
+ * @param index - Position (0-based).
365
+ * @returns Element or `undefined`.
366
+ * @remarks Time O(1)~O(n) depending on implementation, Space O(1)
367
+ */
373
368
  abstract at(index: number): E | undefined;
374
369
 
370
+ /**
371
+ * Remove element at a position.
372
+ * @param pos - Position (0-based).
373
+ * @returns Removed element or `undefined`.
374
+ * @remarks Time O(1)~O(n) depending on implementation, Space O(1)
375
+ */
375
376
  abstract deleteAt(pos: number): E | undefined;
376
377
 
378
+ /**
379
+ * Insert an element/node at a position.
380
+ * @param index - Position (0-based).
381
+ * @param newElementOrNode - Element or node to insert.
382
+ * @returns `true` if inserted.
383
+ * @remarks Time O(1)~O(n) depending on implementation, Space O(1)
384
+ */
377
385
  abstract addAt(index: number, newElementOrNode: E | NODE): boolean;
378
386
 
387
+ /**
388
+ * Create an empty list of the same species.
389
+ * @param options - Runtime options to carry.
390
+ * @returns Empty list (`this` type).
391
+ * @remarks Time O(1), Space O(1)
392
+ */
379
393
  protected abstract _createInstance(options?: LinearBaseOptions<E, R>): this;
380
394
 
395
+ /**
396
+ * Reverse-direction iterator over elements.
397
+ * @returns Iterator of elements from tail to head.
398
+ * @remarks Time O(n), Space O(1)
399
+ */
381
400
  protected abstract _getReverseIterator(...args: any[]): IterableIterator<E>;
382
401
  }
383
402
 
403
+ /**
404
+ * Linked-list specialized linear container.
405
+ * @template E - Element type.
406
+ * @template R - Return type for mapped/derived views.
407
+ * @template NODE - Linked node type.
408
+ * @remarks Time O(1), Space O(1)
409
+ */
384
410
  export abstract class LinearLinkedBase<
385
411
  E,
386
412
  R = any,
387
413
  NODE extends LinkedListNode<E> = LinkedListNode<E>
388
414
  > extends LinearBase<E, R, NODE> {
389
- /**
390
- * The constructor initializes the LinearBase class with optional options, setting the maximum length
391
- * if provided and valid.
392
- * @param [options] - The `options` parameter is an optional object that can be passed to the
393
- * constructor. It is of type `LinearBaseOptions<E, R>`. This object may contain properties such as
394
- * `maxLen`, which is a number representing the maximum length. If `maxLen` is a positive integer,
395
- */
396
415
  protected constructor(options?: LinearBaseOptions<E, R>) {
397
416
  super(options);
398
417
  if (options) {
@@ -402,23 +421,13 @@ export abstract class LinearLinkedBase<
402
421
  }
403
422
 
404
423
  /**
405
- * Time Complexity: O(n)
406
- * Space Complexity: O(1)
407
- *
408
- * The function overrides the indexOf method to improve performance by searching for an element in a
409
- * custom array implementation starting from a specified index.
410
- * @param {E} searchElement - The `searchElement` parameter is the element that you are searching for
411
- * within the array. The `indexOf` method will return the index of the first occurrence of this
412
- * element within the array.
413
- * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the
414
- * index in the array at which to start the search for the `searchElement`. If provided, the search
415
- * will begin at the specified index and continue to the end of the array. If not provided, the
416
- * search will start at index
417
- * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the
418
- * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.
424
+ * Linked-list optimized `indexOf` (forwards scan).
425
+ * @param searchElement - Value to match.
426
+ * @param fromIndex - Start position.
427
+ * @returns Index or `-1`.
428
+ * @remarks Time O(n), Space O(1)
419
429
  */
420
430
  override indexOf(searchElement: E, fromIndex: number = 0): number {
421
- // In order to improve performance, it is best to override this method in the subclass of the array implementation
422
431
  const iterator = this._getIterator();
423
432
  let current = iterator.next();
424
433
 
@@ -438,26 +447,13 @@ export abstract class LinearLinkedBase<
438
447
  }
439
448
 
440
449
  /**
441
- * Time Complexity: O(n)
442
- * Space Complexity: O(1)
443
- *
444
- * The function overrides the lastIndexOf method in TypeScript to improve performance by searching
445
- * for an element in reverse order starting from a specified index.
446
- * @param {E} searchElement - The `searchElement` parameter is the element that you want to find
447
- * within the array. The `lastIndexOf` method searches the array for this element starting from the
448
- * end of the array (or from the specified `fromIndex` if provided) and returns the index of the last
449
- * occurrence of the element
450
- * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the
451
- * index at which to start searching for the `searchElement` in the array. If provided, the search
452
- * will begin at this index and move towards the beginning of the array. If not provided, the search
453
- * will start at the
454
- * @returns The `lastIndexOf` method is being overridden to search for the `searchElement` starting
455
- * from the specified `fromIndex` (defaulting to the end of the array). It iterates over the array in
456
- * reverse order using a custom iterator `_getReverseIterator` and returns the index of the last
457
- * occurrence of the `searchElement` if found, or -1 if not found.
450
+ * Linked-list optimized `lastIndexOf` (reverse scan).
451
+ * @param searchElement - Value to match.
452
+ * @param fromIndex - Start position.
453
+ * @returns Index or `-1`.
454
+ * @remarks Time O(n), Space O(1)
458
455
  */
459
456
  override lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {
460
- // In order to improve performance, it is best to override this method in the subclass of the array implementation
461
457
  const iterator = this._getReverseIterator();
462
458
  let current = iterator.next();
463
459
 
@@ -476,20 +472,14 @@ export abstract class LinearLinkedBase<
476
472
  return -1;
477
473
  }
478
474
 
479
- override concat(...items: LinearBase<E, R>[]): this;
480
-
481
475
  /**
482
- * Time Complexity: O(n + m)
483
- * Space Complexity: O(n + m)
484
- *
485
- * The `concat` function in TypeScript overrides the default behavior to concatenate items into a new
486
- * list, handling both individual elements and instances of `LinearBase`.
487
- * @param {(E | LinearBase<E, R>)[]} items - The `concat` method you provided takes in a variable
488
- * number of arguments of type `E` or `LinearBase<E, R>`. The method concatenates these items to the
489
- * current list and returns a new list with the concatenated items.
490
- * @returns The `concat` method is returning a new instance of the class that it belongs to, with the
491
- * items passed as arguments concatenated to it.
476
+ * Concatenate lists/elements preserving order.
477
+ * @param items - Elements or `LinearBase` instances.
478
+ * @returns New list with combined elements (`this` type).
479
+ * @remarks Time O(sum(length)), Space O(sum(length))
492
480
  */
481
+ override concat(...items: LinearBase<E, R>[]): this;
482
+
493
483
  override concat(...items: (E | LinearBase<E, R>)[]): this {
494
484
  const newList = this.clone();
495
485
 
@@ -505,21 +495,13 @@ export abstract class LinearLinkedBase<
505
495
  }
506
496
 
507
497
  /**
508
- * Time Complexity: O(m)
509
- * Space Complexity: O(m)
510
- *
511
- * The `slice` method is overridden to improve performance by creating a new instance and iterating
512
- * through the array to extract a subset based on the specified start and end indices.
513
- * @param {number} [start=0] - The `start` parameter in the `slice` method specifies the index at
514
- * which to begin extracting elements from the array. If no `start` parameter is provided, the
515
- * default value is 0, indicating that extraction should start from the beginning of the array.
516
- * @param {number} end - The `end` parameter in the `slice` method represents the index at which to
517
- * end the slicing of the array. If not provided, it defaults to the length of the array.
518
- * @returns The `slice` method is returning a new instance of the array implementation with elements
519
- * sliced from the original array based on the `start` and `end` parameters.
498
+ * Slice via forward iteration (no random access required).
499
+ * @param start - Inclusive start (supports negative index).
500
+ * @param end - Exclusive end (supports negative index).
501
+ * @returns New list (`this` type).
502
+ * @remarks Time O(n), Space O(n)
520
503
  */
521
504
  override slice(start: number = 0, end: number = this.length): this {
522
- // In order to improve performance, it is best to override this method in the subclass of the array implementation
523
505
  start = start < 0 ? this.length + start : start;
524
506
  end = end < 0 ? this.length + end : end;
525
507
 
@@ -540,63 +522,48 @@ export abstract class LinearLinkedBase<
540
522
  }
541
523
 
542
524
  /**
543
- * Time Complexity: O(n + m)
544
- * Space Complexity: O(m)
545
- *
546
- * The function overrides the splice method to handle deletion and insertion of elements in a data
547
- * structure while returning the removed elements.
548
- * @param {number} start - The `start` parameter in the `splice` method indicates the index at which
549
- * to start modifying the array.
550
- * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
551
- * number of elements to remove from the array starting at the specified `start` index. If
552
- * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new
553
- * elements can still be inserted at
554
- * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that
555
- * will be inserted into the array at the specified `start` index. These elements can be of any type
556
- * and there can be multiple elements passed as arguments to be inserted into the array.
557
- * @returns The `splice` method is returning a new instance of the data structure that was modified
558
- * by removing elements specified by the `start` and `deleteCount` parameters, and inserting new
559
- * elements provided in the `items` array.
525
+ * Splice by walking node iterators from the start index.
526
+ * @param start - Start index.
527
+ * @param deleteCount - How many elements to remove.
528
+ * @param items - Elements to insert after the splice point.
529
+ * @returns Removed elements as a new list (`this` type).
530
+ * @remarks Time O(n + m), Space O(min(n, m)) where `m = items.length`
560
531
  */
561
532
  override splice(start: number, deleteCount: number = 0, ...items: E[]): this {
562
- const removedList = this._createInstance(); // Used to store deleted elements
533
+ const removedList = this._createInstance();
563
534
 
564
- // Handling negative indexes
565
535
  start = start < 0 ? this.length + start : start;
566
- start = Math.max(0, Math.min(start, this.length)); // Correct start range
567
- deleteCount = Math.max(0, deleteCount); // Make sure deleteCount is non-negative
536
+ start = Math.max(0, Math.min(start, this.length));
537
+ deleteCount = Math.max(0, deleteCount);
568
538
 
569
539
  let currentIndex = 0;
570
540
  let currentNode: NODE | undefined = undefined;
571
541
  let previousNode: NODE | undefined = undefined;
572
542
 
573
- // Find the starting point using an iterator
574
543
  const iterator = this._getNodeIterator();
575
544
  for (const node of iterator) {
576
545
  if (currentIndex === start) {
577
- currentNode = node; // Find the starting node
546
+ currentNode = node;
578
547
  break;
579
548
  }
580
- previousNode = node; // Update the previous node
549
+ previousNode = node;
581
550
  currentIndex++;
582
551
  }
583
552
 
584
- // Delete nodes
585
553
  for (let i = 0; i < deleteCount && currentNode; i++) {
586
- removedList.push(currentNode.value); // Store the deleted value in removedList
587
- const nextNode = currentNode.next; // Save next node
588
- this.delete(currentNode); // Delete current node
554
+ removedList.push(currentNode.value);
555
+ const nextNode = currentNode.next;
556
+ this.delete(currentNode);
589
557
  currentNode = nextNode as NODE;
590
558
  }
591
559
 
592
- // Insert new value
593
560
  for (let i = 0; i < items.length; i++) {
594
561
  if (previousNode) {
595
- this.addAfter(previousNode, items[i]); // Insert after previousNode
596
- previousNode = previousNode.next as NODE; // Move to newly inserted node
562
+ this.addAfter(previousNode, items[i]);
563
+ previousNode = previousNode.next as NODE;
597
564
  } else {
598
- this.addAt(0, items[i]); // Insert at the head of the linked list
599
- previousNode = this._getNodeIterator().next().value; // Update the head node to be the first inserted node
565
+ this.addAt(0, items[i]);
566
+ previousNode = this._getNodeIterator().next().value;
600
567
  }
601
568
  }
602
569
 
@@ -607,23 +574,15 @@ export abstract class LinearLinkedBase<
607
574
 
608
575
  override reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;
609
576
 
610
- override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
611
-
612
577
  /**
613
- * Time Complexity: O(n)
614
- * Space Complexity: O(1)
615
- *
616
- * The function `reduceRight` iterates over an array in reverse order and applies a callback function
617
- * to each element, accumulating a single result.
618
- * @param callbackfn - The `callbackfn` parameter is a function that will be called on each element
619
- * of the array from right to left. It takes four arguments:
620
- * @param {U} [initialValue] - The `initialValue` parameter is an optional value that is used as the
621
- * initial accumulator value in the reduce operation. If provided, the reduce operation starts with
622
- * this initial value and iterates over the elements of the array, applying the callback function to
623
- * each element and the current accumulator value. If `initial
624
- * @returns The `reduceRight` method is returning the final accumulated value after applying the
625
- * callback function to each element in the array from right to left.
578
+ * Right-to-left reduction using reverse iterator.
579
+ * @param callbackfn - `(acc, element, index, self) => acc`.
580
+ * @param initialValue - Initial accumulator.
581
+ * @returns Final accumulator.
582
+ * @remarks Time O(n), Space O(1)
626
583
  */
584
+ override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;
585
+
627
586
  override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {
628
587
  let accumulator = initialValue ?? (0 as U);
629
588
  let index = this.length - 1;
@@ -633,17 +592,52 @@ export abstract class LinearLinkedBase<
633
592
  return accumulator;
634
593
  }
635
594
 
595
+ /**
596
+ * Delete by element or node in a linked list.
597
+ * @param elementOrNode - Element or node.
598
+ * @returns `true` if removed.
599
+ * @remarks Time O(1)~O(n) depending on availability of links, Space O(1)
600
+ */
636
601
  abstract override delete(elementOrNode: E | NODE | undefined): boolean;
637
602
 
603
+ /**
604
+ * Insert new element/node before an existing node.
605
+ * @param existingElementOrNode - Reference element/node.
606
+ * @param newElementOrNode - Element/node to insert.
607
+ * @returns `true` if inserted.
608
+ * @remarks Time O(1)~O(n) depending on reference access, Space O(1)
609
+ */
638
610
  abstract addBefore(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;
639
611
 
612
+ /**
613
+ * Insert new element/node after an existing node.
614
+ * @param existingElementOrNode - Reference element/node.
615
+ * @param newElementOrNode - Element/node to insert.
616
+ * @returns `true` if inserted.
617
+ * @remarks Time O(1)~O(n) depending on reference access, Space O(1)
618
+ */
640
619
  abstract addAfter(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;
641
620
 
621
+ /**
622
+ * Node at index (for random-access emulation).
623
+ * @param index - Position (0-based).
624
+ * @returns Node or `undefined`.
625
+ * @remarks Time O(n), Space O(1)
626
+ */
642
627
  abstract getNodeAt(index: number): NODE | undefined;
643
628
 
629
+ /**
630
+ * Iterate linked nodes from head to tail.
631
+ * @returns Iterator over nodes.
632
+ * @remarks Time O(n), Space O(1)
633
+ */
644
634
  protected abstract _getNodeIterator(...args: any[]): IterableIterator<NODE>;
645
635
 
646
- // protected abstract _getReverseNodeIterator(...args: any[]): IterableIterator<NODE>;
647
-
636
+ /**
637
+ * Get previous node of a given node.
638
+ * @param node - Current node.
639
+ * @returns Previous node or `undefined`.
640
+ * @remarks Time O(1)~O(n) depending on list variant (singly vs doubly), Space O(1)
641
+ */
648
642
  protected abstract _getPrevNode(node: NODE): NODE | undefined;
649
643
  }