avl-tree-typed 2.0.5 → 2.1.1

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 +602 -873
  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 +1 -0
  66. package/dist/utils/number.js +1 -2
  67. package/dist/utils/utils.d.ts +1 -1
  68. package/dist/utils/utils.js +9 -8
  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 +196 -217
  74. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +188 -102
  75. package/src/data-structures/binary-tree/avl-tree.ts +237 -206
  76. package/src/data-structures/binary-tree/binary-tree.ts +665 -896
  77. package/src/data-structures/binary-tree/bst.ts +565 -572
  78. package/src/data-structures/binary-tree/red-black-tree.ts +157 -223
  79. package/src/data-structures/binary-tree/tree-counter.ts +195 -219
  80. package/src/data-structures/binary-tree/tree-multi-map.ts +127 -98
  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 +2 -0
  104. package/src/utils/utils.ts +9 -14
@@ -5,10 +5,15 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import type { ElementCallback, StackOptions } from '../../types';
8
+
9
+ import type { ElementCallback, IterableElementBaseOptions, StackOptions } from '../../types';
9
10
  import { IterableElementBase } from '../base';
10
11
 
11
12
  /**
13
+ * LIFO stack with array storage and optional record→element conversion.
14
+ * @remarks Time O(1), Space O(1)
15
+ * @template E
16
+ * @template R
12
17
  * 1. Last In, First Out (LIFO): The core characteristic of a stack is its last in, first out nature, meaning the last element added to the stack will be the first to be removed.
13
18
  * 2. Uses: Stacks are commonly used for managing a series of tasks or elements that need to be processed in a last in, first out manner. They are widely used in various scenarios, such as in function calls in programming languages, evaluation of arithmetic expressions, and backtracking algorithms.
14
19
  * 3. Performance: Stack operations are typically O(1) in time complexity, meaning that regardless of the stack's size, adding, removing, and viewing the top element are very fast operations.
@@ -138,6 +143,16 @@ import { IterableElementBase } from '../base';
138
143
  * console.log(spans); // [1, 1, 1, 2, 1, 4, 6]
139
144
  */
140
145
  export class Stack<E = any, R = any> extends IterableElementBase<E, R> {
146
+ protected _equals: (a: E, b: E) => boolean = Object.is as unknown as (a: E, b: E) => boolean;
147
+
148
+ /**
149
+ * Create a Stack and optionally bulk-push elements.
150
+ * @remarks Time O(N), Space O(N)
151
+ * @param [elements] - Iterable of elements (or raw records if toElementFn is set).
152
+ * @param [options] - Options such as toElementFn and equality function.
153
+ * @returns New Stack instance.
154
+ */
155
+
141
156
  constructor(elements: Iterable<E> | Iterable<R> = [], options?: StackOptions<E, R>) {
142
157
  super(options);
143
158
  this.pushMany(elements);
@@ -146,220 +161,291 @@ export class Stack<E = any, R = any> extends IterableElementBase<E, R> {
146
161
  protected _elements: E[] = [];
147
162
 
148
163
  /**
149
- * The elements function returns the elements of this set.
150
- * @return An array of elements
164
+ * Get the backing array of elements.
165
+ * @remarks Time O(1), Space O(1)
166
+ * @returns Internal elements array.
151
167
  */
168
+
152
169
  get elements(): E[] {
153
170
  return this._elements;
154
171
  }
155
172
 
156
173
  /**
157
- * The size() function returns the number of elements in an array.
158
- * @returns The size of the elements array.
174
+ * Get the number of stored elements.
175
+ * @remarks Time O(1), Space O(1)
176
+ * @returns Current size.
159
177
  */
178
+
160
179
  get size(): number {
161
180
  return this.elements.length;
162
181
  }
163
182
 
164
183
  /**
165
- * Time Complexity: O(n)
166
- * Space Complexity: O(n)
167
- *
168
- * The function "fromArray" creates a new Stack object from an array of elements.
169
- * @param {E[]} elements - The `elements` parameter is an array of elements of type `E`.
170
- * @returns {Stack} The method is returning a new instance of the Stack class, initialized with the elements from the input
171
- * array.
184
+ * Create a stack from an array of elements.
185
+ * @remarks Time O(N), Space O(N)
186
+ * @template E
187
+ * @template R
188
+ * @param this - The constructor (subclass) to instantiate.
189
+ * @param elements - Array of elements to push in order.
190
+ * @param [options] - Options forwarded to the constructor.
191
+ * @returns A new Stack populated from the array.
172
192
  */
173
- static fromArray<E>(elements: E[]): Stack<E> {
174
- return new Stack(elements);
193
+
194
+ static fromArray<E, R = any>(
195
+ this: new (elements?: Iterable<E> | Iterable<R>, options?: StackOptions<E, R>) => any,
196
+ elements: E[],
197
+ options?: StackOptions<E, R>
198
+ ) {
199
+ return new this(elements, options);
175
200
  }
176
201
 
177
202
  /**
178
- * Time Complexity: O(1)
179
- * Space Complexity: O(1)
180
- *
181
- * The function checks if an array is empty and returns a boolean value.
182
- * @returns A boolean value indicating whether the `_elements` array is empty or not.
203
+ * Check whether the stack is empty.
204
+ * @remarks Time O(1), Space O(1)
205
+ * @returns True if size is 0.
183
206
  */
207
+
184
208
  isEmpty(): boolean {
185
209
  return this.elements.length === 0;
186
210
  }
187
211
 
188
212
  /**
189
- * Time Complexity: O(1)
190
- * Space Complexity: O(1)
191
- *
192
- * The `peek` function returns the last element of an array, or undefined if the array is empty.
193
- * @returns The `peek()` function returns the last element of the `_elements` array, or `undefined` if the array is empty.
213
+ * Get the top element without removing it.
214
+ * @remarks Time O(1), Space O(1)
215
+ * @returns Top element or undefined.
194
216
  */
195
- peek(): E | undefined {
196
- if (this.isEmpty()) return undefined;
197
217
 
198
- return this.elements[this.elements.length - 1];
218
+ peek(): E | undefined {
219
+ return this.isEmpty() ? undefined : this.elements[this.elements.length - 1];
199
220
  }
200
221
 
201
222
  /**
202
- * Time Complexity: O(1)
203
- * Space Complexity: O(1)
204
- *
205
- * The push function adds an element to the stack and returns the updated stack.
206
- * @param {E} element - The parameter "element" is of type E, which means it can be any data type.
207
- * @returns The `push` method is returning the updated `Stack<E>` object.
223
+ * Push one element onto the top.
224
+ * @remarks Time O(1), Space O(1)
225
+ * @param element - Element to push.
226
+ * @returns True when pushed.
208
227
  */
228
+
209
229
  push(element: E): boolean {
210
230
  this.elements.push(element);
211
231
  return true;
212
232
  }
213
233
 
214
234
  /**
215
- * Time Complexity: O(1)
216
- * Space Complexity: O(1)
217
- *
218
- * The `pop` function removes and returns the last element from an array, or returns undefined if the array is empty.
219
- * @returns The `pop()` method is returning the last element of the array `_elements` if the array is not empty. If the
220
- * array is empty, it returns `undefined`.
235
+ * Pop and return the top element.
236
+ * @remarks Time O(1), Space O(1)
237
+ * @returns Removed element or undefined.
221
238
  */
222
- pop(): E | undefined {
223
- if (this.isEmpty()) return;
224
239
 
225
- return this.elements.pop();
240
+ pop(): E | undefined {
241
+ return this.isEmpty() ? undefined : this.elements.pop();
226
242
  }
227
243
 
228
244
  /**
229
- * Time Complexity: O(k)
230
- * Space Complexity: O(1)
231
- *
232
- * The function `pushMany` iterates over elements and pushes them into an array after applying a
233
- * transformation function if provided.
234
- * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `pushMany` function
235
- * is an iterable containing elements of type `E` or `R`. The function iterates over each element in
236
- * the iterable and pushes it into the data structure. If a transformation function `toElementFn` is
237
- * provided, it is used to
238
- * @returns The `pushMany` function is returning an array of boolean values indicating whether each
239
- * element was successfully pushed into the data structure.
245
+ * Push many elements from an iterable.
246
+ * @remarks Time O(N), Space O(1)
247
+ * @param elements - Iterable of elements (or raw records if toElementFn is set).
248
+ * @returns Array of per-element success flags.
240
249
  */
241
- pushMany(elements: Iterable<E> | Iterable<R>) {
250
+
251
+ pushMany(elements: Iterable<E> | Iterable<R>): boolean[] {
242
252
  const ans: boolean[] = [];
243
253
  for (const el of elements) {
244
- if (this.toElementFn) {
245
- ans.push(this.push(this.toElementFn(el as R)));
246
- } else {
247
- ans.push(this.push(el as E));
248
- }
254
+ if (this.toElementFn) ans.push(this.push(this.toElementFn(el as R)));
255
+ else ans.push(this.push(el as E));
249
256
  }
250
257
  return ans;
251
258
  }
252
259
 
253
260
  /**
254
- * Time Complexity: O(n)
255
- * Space Complexity: O(1)
256
- *
257
- * The toArray function returns a copy of the elements in an array.
258
- * @returns An array of type E.
261
+ * Delete the first occurrence of a specific element.
262
+ * @remarks Time O(N), Space O(1)
263
+ * @param element - Element to remove (using the configured equality).
264
+ * @returns True if an element was removed.
259
265
  */
266
+
260
267
  delete(element: E): boolean {
261
- const index = this.elements.indexOf(element);
262
- return this.deleteAt(index);
268
+ const idx = this._indexOfByEquals(element);
269
+ return this.deleteAt(idx);
263
270
  }
264
271
 
265
272
  /**
266
- * Time Complexity: O(n)
267
- * Space Complexity: O(1)
268
- *
269
- * The toArray function returns a copy of the elements in an array.
270
- * @returns An array of type E.
273
+ * Delete the element at an index.
274
+ * @remarks Time O(N), Space O(1)
275
+ * @param index - Zero-based index from the bottom.
276
+ * @returns True if removed.
271
277
  */
278
+
272
279
  deleteAt(index: number): boolean {
280
+ if (index < 0 || index >= this.elements.length) return false;
273
281
  const spliced = this.elements.splice(index, 1);
274
282
  return spliced.length === 1;
275
283
  }
276
284
 
277
285
  /**
278
- * Time Complexity: O(1)
279
- * Space Complexity: O(1)
280
- *
281
- * The clear function clears the elements array.
286
+ * Delete the first element that satisfies a predicate.
287
+ * @remarks Time O(N), Space O(1)
288
+ * @param predicate - Function (value, index, stack) → boolean to decide deletion.
289
+ * @returns True if a match was removed.
282
290
  */
291
+
292
+ deleteWhere(predicate: (value: E, index: number, stack: this) => boolean): boolean {
293
+ for (let i = 0; i < this.elements.length; i++) {
294
+ if (predicate(this.elements[i], i, this)) {
295
+ this.elements.splice(i, 1);
296
+ return true;
297
+ }
298
+ }
299
+ return false;
300
+ }
301
+
302
+ /**
303
+ * Remove all elements and reset storage.
304
+ * @remarks Time O(1), Space O(1)
305
+ * @returns void
306
+ */
307
+
283
308
  clear(): void {
284
309
  this._elements = [];
285
310
  }
286
311
 
287
312
  /**
288
- * Time Complexity: O(n)
289
- * Space Complexity: O(n)
290
- *
291
- * The `clone()` function returns a new `Stack` object with the same elements as the original stack.
292
- * @returns The `clone()` method is returning a new `Stack` object with a copy of the `_elements` array.
313
+ * Deep clone this stack.
314
+ * @remarks Time O(N), Space O(N)
315
+ * @returns A new stack with the same content.
293
316
  */
294
- clone(): Stack<E, R> {
295
- return new Stack<E, R>(this, { toElementFn: this.toElementFn });
317
+
318
+ clone(): this {
319
+ const out = this._createInstance({ toElementFn: this.toElementFn });
320
+ for (const v of this) out.push(v);
321
+ return out;
296
322
  }
297
323
 
298
324
  /**
299
- * Time Complexity: O(n)
300
- * Space Complexity: O(n)
301
- *
302
- * The `filter` function creates a new stack containing elements from the original stack that satisfy
303
- * a given predicate function.
304
- * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
305
- * the current element being iterated over, the index of the current element, and the stack itself.
306
- * It should return a boolean value indicating whether the element should be included in the filtered
307
- * stack or not.
308
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
309
- * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
310
- * passed as the `this` value to the `predicate` function. If `thisArg` is
311
- * @returns The `filter` method is returning a new `Stack` object that contains the elements that
312
- * satisfy the given predicate function.
325
+ * Filter elements into a new stack of the same class.
326
+ * @remarks Time O(N), Space O(N)
327
+ * @param predicate - Predicate (value, index, stack) → boolean to keep value.
328
+ * @param [thisArg] - Value for `this` inside the predicate.
329
+ * @returns A new stack with kept values.
313
330
  */
314
- filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Stack<E, R> {
315
- const newStack = new Stack<E, R>([], { toElementFn: this.toElementFn });
331
+
332
+ filter(predicate: ElementCallback<E, R, boolean>, thisArg?: unknown): this {
333
+ const out = this._createInstance({ toElementFn: this.toElementFn });
316
334
  let index = 0;
317
- for (const el of this) {
318
- if (predicate.call(thisArg, el, index, this)) {
319
- newStack.push(el);
320
- }
335
+ for (const v of this) {
336
+ if (predicate.call(thisArg, v, index, this)) out.push(v);
321
337
  index++;
322
338
  }
323
- return newStack;
339
+ return out;
324
340
  }
325
341
 
326
342
  /**
327
- * Time Complexity: O(n)
328
- * Space Complexity: O(n)
329
- *
330
- * The `map` function takes a callback function and applies it to each element in the stack,
331
- * returning a new stack with the results.
332
- * @param callback - The callback parameter is a function that will be called for each element in the
333
- * stack. It takes three arguments: the current element, the index of the element, and the stack
334
- * itself. It should return a new value that will be added to the new stack.
335
- * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
336
- * transform the raw element (`RM`) into a new element (`EM`) before pushing it into the new stack.
337
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
338
- * specify the value of `this` within the callback function. It is used to set the context or scope
339
- * in which the callback function will be executed. If `thisArg` is provided, it will be used as the
340
- * value of
341
- * @returns a new Stack object with elements of type EM and raw elements of type RM.
343
+ * Map values into a new stack of the same element type.
344
+ * @remarks Time O(N), Space O(N)
345
+ * @param callback - Mapping function (value, index, stack) → newValue.
346
+ * @param [thisArg] - Value for `this` inside the callback.
347
+ * @returns A new stack with mapped values.
342
348
  */
343
- map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Stack<EM, RM> {
344
- const newStack = new Stack<EM, RM>([], { toElementFn });
349
+
350
+ mapSame(callback: ElementCallback<E, R, E>, thisArg?: unknown): this {
351
+ const out = this._createInstance({ toElementFn: this.toElementFn });
345
352
  let index = 0;
346
- for (const el of this) {
347
- newStack.push(callback.call(thisArg, el, index, this));
353
+ for (const v of this) {
354
+ const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
355
+ out.push(mv);
356
+ }
357
+ return out;
358
+ }
359
+
360
+ /**
361
+ * Map values into a new stack (possibly different element type).
362
+ * @remarks Time O(N), Space O(N)
363
+ * @template EM
364
+ * @template RM
365
+ * @param callback - Mapping function (value, index, stack) → newElement.
366
+ * @param [options] - Options for the output stack (e.g., toElementFn).
367
+ * @param [thisArg] - Value for `this` inside the callback.
368
+ * @returns A new Stack with mapped elements.
369
+ */
370
+
371
+ map<EM, RM>(
372
+ callback: ElementCallback<E, R, EM>,
373
+ options?: IterableElementBaseOptions<EM, RM>,
374
+ thisArg?: unknown
375
+ ): Stack<EM, RM> {
376
+ const out = this._createLike<EM, RM>([], { ...(options ?? {}) });
377
+ let index = 0;
378
+ for (const v of this) {
379
+ out.push(thisArg === undefined ? callback(v, index, this) : callback.call(thisArg, v, index, this));
348
380
  index++;
349
381
  }
350
- return newStack;
382
+ return out;
383
+ }
384
+
385
+ /**
386
+ * Set the equality comparator used by delete/search operations.
387
+ * @remarks Time O(1), Space O(1)
388
+ * @param equals - Equality predicate (a, b) → boolean.
389
+ * @returns This stack.
390
+ */
391
+
392
+ setEquality(equals: (a: E, b: E) => boolean): this {
393
+ this._equals = equals;
394
+ return this;
395
+ }
396
+
397
+ /**
398
+ * (Protected) Find the index of a target element using the equality function.
399
+ * @remarks Time O(N), Space O(1)
400
+ * @param target - Element to search for.
401
+ * @returns Index or -1 if not found.
402
+ */
403
+
404
+ protected _indexOfByEquals(target: E): number {
405
+ for (let i = 0; i < this.elements.length; i++) if (this._equals(this.elements[i], target)) return i;
406
+ return -1;
407
+ }
408
+
409
+ /**
410
+ * (Protected) Create an empty instance of the same concrete class.
411
+ * @remarks Time O(1), Space O(1)
412
+ * @param [options] - Options forwarded to the constructor.
413
+ * @returns An empty like-kind stack instance.
414
+ */
415
+
416
+ protected _createInstance(options?: StackOptions<E, R>): this {
417
+ const Ctor = this.constructor as new (elements?: Iterable<E> | Iterable<R>, options?: StackOptions<E, R>) => this;
418
+ return new Ctor([], options);
351
419
  }
352
420
 
353
421
  /**
354
- * Time Complexity: O(n)
355
- * Space Complexity: O(n)
356
- *
357
- * Custom iterator for the Stack class.
358
- * @returns An iterator object.
422
+ * (Protected) Create a like-kind stack and seed it from an iterable.
423
+ * @remarks Time O(N), Space O(N)
424
+ * @template T
425
+ * @template RR
426
+ * @param [elements] - Iterable used to seed the new stack.
427
+ * @param [options] - Options forwarded to the constructor.
428
+ * @returns A like-kind Stack instance.
359
429
  */
430
+
431
+ protected _createLike<T = E, RR = R>(
432
+ elements: Iterable<T> | Iterable<RR> = [],
433
+ options?: StackOptions<T, RR>
434
+ ): Stack<T, RR> {
435
+ const Ctor = this.constructor as new (
436
+ elements?: Iterable<T> | Iterable<RR>,
437
+ options?: StackOptions<T, RR>
438
+ ) => Stack<T, RR>;
439
+ return new Ctor(elements, options);
440
+ }
441
+
442
+ /**
443
+ * (Protected) Iterate elements from bottom to top.
444
+ * @remarks Time O(N), Space O(1)
445
+ * @returns Iterator of elements.
446
+ */
447
+
360
448
  protected *_getIterator(): IterableIterator<E> {
361
- for (let i = 0; i < this.elements.length; i++) {
362
- yield this.elements[i];
363
- }
449
+ for (let i = 0; i < this.elements.length; i++) yield this.elements[i];
364
450
  }
365
451
  }