data-structure-typed 1.48.1 → 1.48.2

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 (114) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +24 -18
  3. package/benchmark/report.html +16 -16
  4. package/benchmark/report.json +182 -182
  5. package/dist/cjs/data-structures/base/index.d.ts +1 -0
  6. package/dist/cjs/data-structures/base/index.js +18 -0
  7. package/dist/cjs/data-structures/base/index.js.map +1 -0
  8. package/dist/cjs/data-structures/base/iterable-base.d.ts +232 -0
  9. package/dist/cjs/data-structures/base/iterable-base.js +313 -0
  10. package/dist/cjs/data-structures/base/iterable-base.js.map +1 -0
  11. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +36 -69
  12. package/dist/cjs/data-structures/binary-tree/binary-tree.js +78 -129
  13. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  14. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +44 -6
  15. package/dist/cjs/data-structures/graph/abstract-graph.js +50 -27
  16. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  17. package/dist/cjs/data-structures/hash/hash-map.d.ts +59 -100
  18. package/dist/cjs/data-structures/hash/hash-map.js +69 -173
  19. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  20. package/dist/cjs/data-structures/heap/heap.d.ts +50 -7
  21. package/dist/cjs/data-structures/heap/heap.js +60 -30
  22. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  23. package/dist/cjs/data-structures/index.d.ts +1 -0
  24. package/dist/cjs/data-structures/index.js +1 -0
  25. package/dist/cjs/data-structures/index.js.map +1 -1
  26. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +38 -51
  27. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +46 -73
  28. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  29. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +32 -51
  30. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +40 -73
  31. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  32. package/dist/cjs/data-structures/queue/deque.d.ts +29 -51
  33. package/dist/cjs/data-structures/queue/deque.js +36 -71
  34. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  35. package/dist/cjs/data-structures/queue/queue.d.ts +49 -48
  36. package/dist/cjs/data-structures/queue/queue.js +69 -82
  37. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  38. package/dist/cjs/data-structures/stack/stack.d.ts +43 -10
  39. package/dist/cjs/data-structures/stack/stack.js +50 -31
  40. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  41. package/dist/cjs/data-structures/trie/trie.d.ts +41 -6
  42. package/dist/cjs/data-structures/trie/trie.js +53 -32
  43. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  44. package/dist/cjs/types/data-structures/base/base.d.ts +5 -0
  45. package/dist/cjs/types/data-structures/base/base.js +3 -0
  46. package/dist/cjs/types/data-structures/base/base.js.map +1 -0
  47. package/dist/cjs/types/data-structures/base/index.d.ts +1 -0
  48. package/dist/cjs/types/data-structures/base/index.js +18 -0
  49. package/dist/cjs/types/data-structures/base/index.js.map +1 -0
  50. package/dist/cjs/types/data-structures/index.d.ts +1 -0
  51. package/dist/cjs/types/data-structures/index.js +1 -0
  52. package/dist/cjs/types/data-structures/index.js.map +1 -1
  53. package/dist/mjs/data-structures/base/index.d.ts +1 -0
  54. package/dist/mjs/data-structures/base/index.js +1 -0
  55. package/dist/mjs/data-structures/base/iterable-base.d.ts +232 -0
  56. package/dist/mjs/data-structures/base/iterable-base.js +307 -0
  57. package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +36 -69
  58. package/dist/mjs/data-structures/binary-tree/binary-tree.js +78 -129
  59. package/dist/mjs/data-structures/graph/abstract-graph.d.ts +44 -6
  60. package/dist/mjs/data-structures/graph/abstract-graph.js +52 -27
  61. package/dist/mjs/data-structures/hash/hash-map.d.ts +59 -100
  62. package/dist/mjs/data-structures/hash/hash-map.js +69 -173
  63. package/dist/mjs/data-structures/heap/heap.d.ts +50 -7
  64. package/dist/mjs/data-structures/heap/heap.js +60 -30
  65. package/dist/mjs/data-structures/index.d.ts +1 -0
  66. package/dist/mjs/data-structures/index.js +1 -0
  67. package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +38 -51
  68. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +46 -73
  69. package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +32 -51
  70. package/dist/mjs/data-structures/linked-list/singly-linked-list.js +40 -73
  71. package/dist/mjs/data-structures/queue/deque.d.ts +29 -51
  72. package/dist/mjs/data-structures/queue/deque.js +36 -71
  73. package/dist/mjs/data-structures/queue/queue.d.ts +49 -48
  74. package/dist/mjs/data-structures/queue/queue.js +66 -79
  75. package/dist/mjs/data-structures/stack/stack.d.ts +43 -10
  76. package/dist/mjs/data-structures/stack/stack.js +50 -31
  77. package/dist/mjs/data-structures/trie/trie.d.ts +41 -6
  78. package/dist/mjs/data-structures/trie/trie.js +53 -32
  79. package/dist/mjs/types/data-structures/base/base.d.ts +5 -0
  80. package/dist/mjs/types/data-structures/base/base.js +1 -0
  81. package/dist/mjs/types/data-structures/base/index.d.ts +1 -0
  82. package/dist/mjs/types/data-structures/base/index.js +1 -0
  83. package/dist/mjs/types/data-structures/index.d.ts +1 -0
  84. package/dist/mjs/types/data-structures/index.js +1 -0
  85. package/dist/umd/data-structure-typed.js +846 -715
  86. package/dist/umd/data-structure-typed.min.js +2 -2
  87. package/dist/umd/data-structure-typed.min.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/data-structures/base/index.ts +1 -0
  90. package/src/data-structures/base/iterable-base.ts +329 -0
  91. package/src/data-structures/binary-tree/binary-tree.ts +82 -138
  92. package/src/data-structures/graph/abstract-graph.ts +55 -28
  93. package/src/data-structures/hash/hash-map.ts +76 -185
  94. package/src/data-structures/heap/heap.ts +63 -36
  95. package/src/data-structures/index.ts +1 -0
  96. package/src/data-structures/linked-list/doubly-linked-list.ts +50 -79
  97. package/src/data-structures/linked-list/singly-linked-list.ts +45 -80
  98. package/src/data-structures/queue/deque.ts +40 -82
  99. package/src/data-structures/queue/queue.ts +72 -87
  100. package/src/data-structures/stack/stack.ts +53 -34
  101. package/src/data-structures/trie/trie.ts +58 -35
  102. package/src/types/data-structures/base/base.ts +6 -0
  103. package/src/types/data-structures/base/index.ts +1 -0
  104. package/src/types/data-structures/index.ts +1 -0
  105. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +10 -10
  106. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +10 -10
  107. package/test/unit/data-structures/binary-tree/bst.test.ts +10 -10
  108. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +8 -8
  109. package/test/unit/data-structures/binary-tree/tree-multimap.test.ts +10 -10
  110. package/test/unit/data-structures/graph/directed-graph.test.ts +4 -4
  111. package/test/unit/data-structures/hash/hash-map.test.ts +2 -2
  112. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +28 -0
  113. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +25 -0
  114. package/test/unit/data-structures/queue/deque.test.ts +25 -0
@@ -4,42 +4,10 @@
4
4
  * @class
5
5
  */
6
6
  import { SinglyLinkedList } from '../linked-list';
7
+ import { IterableElementBase } from "../base";
8
+ import { ElementCallback } from "../../types";
7
9
 
8
- export class LinkedListQueue<E = any> extends SinglyLinkedList<E> {
9
- /**
10
- * The enqueue function adds a value to the end of an array.
11
- * @param {E} value - The value parameter represents the value that you want to add to the queue.
12
- */
13
- enqueue(value: E) {
14
- this.push(value);
15
- }
16
-
17
- /**
18
- * The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty.
19
- * @returns The method is returning the element at the front of the queue, or undefined if the queue is empty.
20
- */
21
- dequeue(): E | undefined {
22
- return this.shift();
23
- }
24
-
25
- /**
26
- * The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
27
- * @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
28
- */
29
- getFirst(): E | undefined {
30
- return this.head?.value;
31
- }
32
-
33
- /**
34
- * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
35
- * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
36
- */
37
- peek(): E | undefined {
38
- return this.getFirst();
39
- }
40
- }
41
-
42
- export class Queue<E = any> {
10
+ export class Queue<E = any> extends IterableElementBase<E> {
43
11
  /**
44
12
  * The constructor initializes an instance of a class with an optional array of elements and sets the offset to 0.
45
13
  * @param {E[]} [elements] - The `elements` parameter is an optional array of elements of type `E`. If provided, it
@@ -47,6 +15,7 @@ export class Queue<E = any> {
47
15
  * initialized as an empty array.
48
16
  */
49
17
  constructor(elements?: E[]) {
18
+ super();
50
19
  this._nodes = elements || [];
51
20
  this._offset = 0;
52
21
  }
@@ -304,34 +273,6 @@ export class Queue<E = any> {
304
273
  console.log([...this]);
305
274
  }
306
275
 
307
- * [Symbol.iterator]() {
308
- for (const item of this.nodes) {
309
- yield item;
310
- }
311
- }
312
-
313
- /**
314
- * Time Complexity: O(n)
315
- * Space Complexity: O(1)
316
- */
317
-
318
- /**
319
- * Time Complexity: O(n)
320
- * Space Complexity: O(1)
321
- *
322
- * The `forEach` function iterates over each element in a deque and applies a callback function to
323
- * each element.
324
- * @param callback - The callback parameter is a function that will be called for each element in the
325
- * deque. It takes three parameters:
326
- */
327
- forEach(callback: (element: E, index: number, queue: this) => void) {
328
- let index = 0;
329
- for (const el of this) {
330
- callback(el, index, this);
331
- index++;
332
- }
333
- }
334
-
335
276
  /**
336
277
  * Time Complexity: O(n)
337
278
  * Space Complexity: O(n)
@@ -341,18 +282,23 @@ export class Queue<E = any> {
341
282
  * Time Complexity: O(n)
342
283
  * Space Complexity: O(n)
343
284
  *
344
- * The `filter` function creates a new deque containing only the elements that satisfy the given
345
- * predicate function.
346
- * @param predicate - The `predicate` parameter is a function that takes three arguments: `element`,
347
- * `index`, and `deque`.
348
- * @returns The `filter` method is returning a new `Queue` object that contains only the elements
349
- * that satisfy the given `predicate` function.
350
- */
351
- filter(predicate: (element: E, index: number, queue: this) => boolean): Queue<E> {
285
+ * The `filter` function creates a new `Queue` object containing elements from the original `Queue`
286
+ * that satisfy a given predicate function.
287
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
288
+ * the current element being iterated over, the index of the current element, and the queue itself.
289
+ * It should return a boolean value indicating whether the element should be included in the filtered
290
+ * queue or not.
291
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
292
+ * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
293
+ * passed as the `this` value to the `predicate` function. If `thisArg` is
294
+ * @returns The `filter` method is returning a new `Queue` object that contains the elements that
295
+ * satisfy the given predicate function.
296
+ */
297
+ filter(predicate: ElementCallback<E, boolean>, thisArg?: any): Queue<E> {
352
298
  const newDeque = new Queue<E>([]);
353
299
  let index = 0;
354
300
  for (const el of this) {
355
- if (predicate(el, index, this)) {
301
+ if (predicate.call(thisArg, el, index, this)) {
356
302
  newDeque.push(el);
357
303
  }
358
304
  index++;
@@ -364,33 +310,72 @@ export class Queue<E = any> {
364
310
  * Time Complexity: O(n)
365
311
  * Space Complexity: O(n)
366
312
  */
367
-
368
313
  /**
369
314
  * Time Complexity: O(n)
370
315
  * Space Complexity: O(n)
371
316
  *
372
- * The `map` function takes a callback function and applies it to each element in the deque,
373
- * returning a new deque with the results.
374
- * @param callback - The `callback` parameter is a function that takes three arguments:
375
- * @returns The `map` method is returning a new `Queue` object with the transformed elements.
376
- */
377
- map<T>(callback: (element: E, index: number, queue: this) => T): Queue<T> {
317
+ * The `map` function takes a callback function and applies it to each element in the queue,
318
+ * returning a new queue with the results.
319
+ * @param callback - The callback parameter is a function that will be called for each element in the
320
+ * queue. It takes three arguments: the current element, the index of the current element, and the
321
+ * queue itself. The callback function should return a new value that will be added to the new queue.
322
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
323
+ * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
324
+ * passed as the `this` value to the `callback` function. If `thisArg` is
325
+ * @returns The `map` function is returning a new `Queue` object with the transformed elements.
326
+ */
327
+ map<T>(callback: ElementCallback<E, T>, thisArg?: any): Queue<T> {
378
328
  const newDeque = new Queue<T>([]);
379
329
  let index = 0;
380
330
  for (const el of this) {
381
- newDeque.push(callback(el, index, this));
331
+ newDeque.push(callback.call(thisArg, el, index, this));
382
332
  index++;
383
333
  }
384
334
  return newDeque;
385
335
  }
386
336
 
387
- reduce<T>(callback: (accumulator: T, element: E, index: number, queue: this) => T, initialValue: T): T {
388
- let accumulator = initialValue;
389
- let index = 0;
390
- for (const el of this) {
391
- accumulator = callback(accumulator, el, index, this);
392
- index++;
337
+ /**
338
+ * Time Complexity: O(n)
339
+ * Space Complexity: O(n)
340
+ */
341
+
342
+ protected* _getIterator() {
343
+ for (const item of this.nodes) {
344
+ yield item;
393
345
  }
394
- return accumulator;
395
346
  }
396
347
  }
348
+
349
+ export class LinkedListQueue<E = any> extends SinglyLinkedList<E> {
350
+ /**
351
+ * The enqueue function adds a value to the end of an array.
352
+ * @param {E} value - The value parameter represents the value that you want to add to the queue.
353
+ */
354
+ enqueue(value: E) {
355
+ this.push(value);
356
+ }
357
+
358
+ /**
359
+ * The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty.
360
+ * @returns The method is returning the element at the front of the queue, or undefined if the queue is empty.
361
+ */
362
+ dequeue(): E | undefined {
363
+ return this.shift();
364
+ }
365
+
366
+ /**
367
+ * The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
368
+ * @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
369
+ */
370
+ getFirst(): E | undefined {
371
+ return this.head?.value;
372
+ }
373
+
374
+ /**
375
+ * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
376
+ * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
377
+ */
378
+ peek(): E | undefined {
379
+ return this.getFirst();
380
+ }
381
+ }
@@ -1,9 +1,12 @@
1
+ import { IterableElementBase } from "../base";
2
+ import { ElementCallback } from "../../types";
3
+
1
4
  /**
2
5
  * @license MIT
3
6
  * @copyright Tyler Zeng <zrwusa@gmail.com>
4
7
  * @class
5
8
  */
6
- export class Stack<E = any> {
9
+ export class Stack<E = any> extends IterableElementBase<E> {
7
10
  /**
8
11
  * The constructor initializes an array of elements, which can be provided as an optional parameter.
9
12
  * @param {E[]} [elements] - The `elements` parameter is an optional parameter of type `E[]`, which represents an array
@@ -11,6 +14,7 @@ export class Stack<E = any> {
11
14
  * is provided and is an array, it is assigned to the `_elements
12
15
  */
13
16
  constructor(elements?: Iterable<E>) {
17
+ super();
14
18
  this._elements = [];
15
19
  if (elements) {
16
20
  for (const el of elements) {
@@ -154,33 +158,31 @@ export class Stack<E = any> {
154
158
  }
155
159
 
156
160
  /**
157
- * Custom iterator for the Stack class.
158
- * @returns An iterator object.
161
+ * Time Complexity: O(n)
162
+ * Space Complexity: O(n)
159
163
  */
160
- * [Symbol.iterator]() {
161
- for (let i = 0; i < this.elements.length; i++) {
162
- yield this.elements[i];
163
- }
164
- }
165
164
 
166
165
  /**
167
- * Applies a function to each element of the stack.
168
- * @param {function(E): void} callback - A function to apply to each element.
169
- */
170
- forEach(callback: (element: E, index: number, stack: this) => void): void {
171
- let index = 0;
172
- for (const el of this) {
173
- callback(el, index, this);
174
- index++;
175
- }
176
- }
177
-
178
-
179
- filter(predicate: (element: E, index: number, stack: this) => boolean): Stack<E> {
166
+ * Time Complexity: O(n)
167
+ * Space Complexity: O(n)
168
+ *
169
+ * The `filter` function creates a new stack containing elements from the original stack that satisfy
170
+ * a given predicate function.
171
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
172
+ * the current element being iterated over, the index of the current element, and the stack itself.
173
+ * It should return a boolean value indicating whether the element should be included in the filtered
174
+ * stack or not.
175
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
176
+ * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
177
+ * passed as the `this` value to the `predicate` function. If `thisArg` is
178
+ * @returns The `filter` method is returning a new `Stack` object that contains the elements that
179
+ * satisfy the given predicate function.
180
+ */
181
+ filter(predicate: ElementCallback<E, boolean>, thisArg?: any): Stack<E> {
180
182
  const newStack = new Stack<E>();
181
183
  let index = 0;
182
184
  for (const el of this) {
183
- if (predicate(el, index, this)) {
185
+ if (predicate.call(thisArg, el, index, this)) {
184
186
  newStack.push(el);
185
187
  }
186
188
  index++;
@@ -188,28 +190,45 @@ export class Stack<E = any> {
188
190
  return newStack;
189
191
  }
190
192
 
193
+ /**
194
+ * Time Complexity: O(n)
195
+ * Space Complexity: O(n)
196
+ */
191
197
 
192
- map<T>(callback: (element: E, index: number, stack: this) => T): Stack<T> {
198
+ /**
199
+ * Time Complexity: O(n)
200
+ * Space Complexity: O(n)
201
+ *
202
+ * The `map` function takes a callback function and applies it to each element in the stack,
203
+ * returning a new stack with the results.
204
+ * @param callback - The `callback` parameter is a function that will be called for each element in
205
+ * the stack. It takes three arguments:
206
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
207
+ * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
208
+ * passed as the `this` value to the `callback` function. If `thisArg` is
209
+ * @returns The `map` method is returning a new `Stack` object.
210
+ */
211
+ map<T>(callback: ElementCallback<E, T>, thisArg?: any): Stack<T> {
193
212
  const newStack = new Stack<T>();
194
213
  let index = 0;
195
214
  for (const el of this) {
196
- newStack.push(callback(el, index, this));
215
+ newStack.push(callback.call(thisArg, el, index, this));
197
216
  index++;
198
217
  }
199
218
  return newStack;
200
219
  }
201
220
 
202
- reduce<T>(callback: (accumulator: T, element: E, index: number, stack: this) => T, initialValue: T): T {
203
- let accumulator = initialValue;
204
- let index = 0;
205
- for (const el of this) {
206
- accumulator = callback(accumulator, el, index, this);
207
- index++;
208
- }
209
- return accumulator;
210
- }
211
-
212
221
  print(): void {
213
222
  console.log([...this]);
214
223
  }
224
+
225
+ /**
226
+ * Custom iterator for the Stack class.
227
+ * @returns An iterator object.
228
+ */
229
+ protected* _getIterator() {
230
+ for (let i = 0; i < this.elements.length; i++) {
231
+ yield this.elements[i];
232
+ }
233
+ }
215
234
  }
@@ -6,6 +6,9 @@
6
6
  * @license MIT License
7
7
  */
8
8
 
9
+ import { IterableElementBase } from "../base";
10
+ import { ElementCallback } from "../../types";
11
+
9
12
  /**
10
13
  * TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,
11
14
  * and a flag indicating whether it's the end of a word.
@@ -25,8 +28,9 @@ export class TrieNode {
25
28
  /**
26
29
  * Trie represents a Trie data structure. It provides basic Trie operations and additional methods.
27
30
  */
28
- export class Trie {
31
+ export class Trie extends IterableElementBase<string> {
29
32
  constructor(words?: string[], caseSensitive = true) {
33
+ super();
30
34
  this._root = new TrieNode('');
31
35
  this._caseSensitive = caseSensitive;
32
36
  this._size = 0;
@@ -339,32 +343,30 @@ export class Trie {
339
343
  return words;
340
344
  }
341
345
 
342
- * [Symbol.iterator](): IterableIterator<string> {
343
- function* _dfs(node: TrieNode, path: string): IterableIterator<string> {
344
- if (node.isEnd) {
345
- yield path;
346
- }
347
- for (const [char, childNode] of node.children) {
348
- yield* _dfs(childNode, path + char);
349
- }
350
- }
351
-
352
- yield* _dfs(this.root, '');
353
- }
354
-
355
- forEach(callback: (word: string, index: number, trie: this) => void): void {
356
- let index = 0;
357
- for (const word of this) {
358
- callback(word, index, this);
359
- index++;
360
- }
361
- }
346
+ /**
347
+ * Time Complexity: O(n)
348
+ * Space Complexity: O(n)
349
+ */
362
350
 
363
- filter(predicate: (word: string, index: number, trie: this) => boolean): string[] {
351
+ /**
352
+ * Time Complexity: O(n)
353
+ * Space Complexity: O(n)
354
+ *
355
+ * The `filter` function takes a predicate function and returns a new array containing all the
356
+ * elements for which the predicate function returns true.
357
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
358
+ * `word`, `index`, and `this`. It should return a boolean value indicating whether the current
359
+ * element should be included in the filtered results or not.
360
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
361
+ * specify the value of `this` within the `predicate` function. It is used when you want to bind a
362
+ * specific object as the context for the `predicate` function. If `thisArg` is provided, it will be
363
+ * @returns The `filter` method is returning an array of strings (`string[]`).
364
+ */
365
+ filter(predicate: ElementCallback<string, boolean>, thisArg?: any): string[] {
364
366
  const results: string[] = [];
365
367
  let index = 0;
366
368
  for (const word of this) {
367
- if (predicate(word, index, this)) {
369
+ if (predicate.call(thisArg, word, index, this)) {
368
370
  results.push(word);
369
371
  }
370
372
  index++;
@@ -372,30 +374,51 @@ export class Trie {
372
374
  return results;
373
375
  }
374
376
 
375
- map(callback: (word: string, index: number, trie: this) => string): Trie {
377
+ /**
378
+ * Time Complexity: O(n)
379
+ * Space Complexity: O(n)
380
+ */
381
+
382
+ /**
383
+ * Time Complexity: O(n)
384
+ * Space Complexity: O(n)
385
+ *
386
+ * The `map` function creates a new Trie by applying a callback function to each element in the Trie.
387
+ * @param callback - The callback parameter is a function that will be called for each element in the
388
+ * Trie. It takes three arguments: the current element in the Trie, the index of the current element,
389
+ * and the Trie itself. The callback function should return a new value for the element.
390
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
391
+ * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
392
+ * passed as the `this` value to the `callback` function. If `thisArg` is
393
+ * @returns The `map` function is returning a new Trie object.
394
+ */
395
+ map(callback: ElementCallback<string, string>, thisArg?: any): Trie {
376
396
  const newTrie = new Trie();
377
397
  let index = 0;
378
398
  for (const word of this) {
379
- newTrie.add(callback(word, index, this));
399
+ newTrie.add(callback.call(thisArg, word, index, this));
380
400
  index++;
381
401
  }
382
402
  return newTrie;
383
403
  }
384
404
 
385
- reduce<T>(callback: (accumulator: T, word: string, index: number, trie: this) => T, initialValue: T): T {
386
- let accumulator = initialValue;
387
- let index = 0;
388
- for (const word of this) {
389
- accumulator = callback(accumulator, word, index, this);
390
- index++;
391
- }
392
- return accumulator;
393
- }
394
-
395
405
  print() {
396
406
  console.log([...this]);
397
407
  }
398
408
 
409
+ protected* _getIterator(): IterableIterator<string> {
410
+ function* _dfs(node: TrieNode, path: string): IterableIterator<string> {
411
+ if (node.isEnd) {
412
+ yield path;
413
+ }
414
+ for (const [char, childNode] of node.children) {
415
+ yield* _dfs(childNode, path + char);
416
+ }
417
+ }
418
+
419
+ yield* _dfs(this.root, '');
420
+ }
421
+
399
422
  /**
400
423
  * Time Complexity: O(M), where M is the length of the input string.
401
424
  * Space Complexity: O(1) - Constant space.
@@ -0,0 +1,6 @@
1
+ import { IterableElementBase, IterablePairBase } from "../../../data-structures";
2
+
3
+ export type PairCallback<K, V, R> = (value: V, key: K, index: number, container: IterablePairBase<K, V>) => R;
4
+ export type ElementCallback<V, R> = (element: V, index: number, container: IterableElementBase<V>) => R;
5
+ export type ReducePairCallback<K, V, R> = (accumulator: R, value: V, key: K, index: number, container: IterablePairBase<K, V>) => R;
6
+ export type ReduceElementCallback<V, R> = (accumulator: R, element: V, index: number, container: IterableElementBase<V>) => R;
@@ -0,0 +1 @@
1
+ export * from './base';
@@ -9,3 +9,4 @@ export * from './queue';
9
9
  export * from './stack';
10
10
  export * from './tree';
11
11
  export * from './trie';
12
+ export * from './base';
@@ -305,30 +305,30 @@ describe('AVLTree iterative methods test', () => {
305
305
 
306
306
  test('forEach should iterate over all elements', () => {
307
307
  const mockCallback = jest.fn();
308
- avl.forEach((entry) => {
309
- mockCallback(entry);
308
+ avl.forEach((value, key) => {
309
+ mockCallback(value, key);
310
310
  });
311
311
 
312
312
  expect(mockCallback.mock.calls.length).toBe(3);
313
- expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
314
- expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
315
- expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
313
+ expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
314
+ expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
315
+ expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
316
316
  });
317
317
 
318
318
  test('filter should return a new tree with filtered elements', () => {
319
- const filteredTree = avl.filter(([key]) => key > 1);
319
+ const filteredTree = avl.filter((value, key) => key > 1);
320
320
  expect(filteredTree.size).toBe(2);
321
321
  expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
322
322
  });
323
323
 
324
324
  test('map should return a new tree with modified elements', () => {
325
- const mappedTree = avl.map(([key]) => (key * 2).toString());
325
+ const mappedTree = avl.map((value, key) => (key * 2).toString());
326
326
  expect(mappedTree.size).toBe(3);
327
327
  expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
328
328
  });
329
329
 
330
330
  test('reduce should accumulate values', () => {
331
- const sum = avl.reduce((acc, [key]) => acc + key, 0);
331
+ const sum = avl.reduce((acc, value, key) => acc + key, 0);
332
332
  expect(sum).toBe(6);
333
333
  });
334
334
 
@@ -350,11 +350,11 @@ describe('AVLTree iterative methods test', () => {
350
350
 
351
351
  test('should keys', () => {
352
352
  const keys = avl.keys();
353
- expect(keys).toEqual([1, 2, 3]);
353
+ expect([...keys]).toEqual([1, 2, 3]);
354
354
  });
355
355
 
356
356
  test('should values', () => {
357
357
  const values = avl.values();
358
- expect(values).toEqual(['a', 'b', 'c']);
358
+ expect([...values]).toEqual(['a', 'b', 'c']);
359
359
  });
360
360
  });
@@ -580,30 +580,30 @@ describe('BinaryTree iterative methods test', () => {
580
580
 
581
581
  test('forEach should iterate over all elements', () => {
582
582
  const mockCallback = jest.fn();
583
- binaryTree.forEach((entry) => {
584
- mockCallback(entry);
583
+ binaryTree.forEach((value, key) => {
584
+ mockCallback(value, key);
585
585
  });
586
586
 
587
587
  expect(mockCallback.mock.calls.length).toBe(3);
588
- expect(mockCallback.mock.calls[0][0]).toEqual([2, 'b']);
589
- expect(mockCallback.mock.calls[1][0]).toEqual([1, 'a']);
590
- expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
588
+ expect(mockCallback.mock.calls[0]).toEqual(['b', 2]);
589
+ expect(mockCallback.mock.calls[1]).toEqual(['a', 1]);
590
+ expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
591
591
  });
592
592
 
593
593
  test('filter should return a new tree with filtered elements', () => {
594
- const filteredTree = binaryTree.filter(([key]) => key > 1);
594
+ const filteredTree = binaryTree.filter((value, key) => key > 1);
595
595
  expect(filteredTree.size).toBe(2);
596
596
  expect([...filteredTree]).toEqual([[3, 'c'], [2, 'b']]);
597
597
  });
598
598
 
599
599
  test('map should return a new tree with modified elements', () => {
600
- const mappedTree = binaryTree.map(([key]) => (key * 2).toString());
600
+ const mappedTree = binaryTree.map((value, key) => (key * 2).toString());
601
601
  expect(mappedTree.size).toBe(3);
602
602
  expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
603
603
  });
604
604
 
605
605
  test('reduce should accumulate values', () => {
606
- const sum = binaryTree.reduce((acc, [key]) => acc + key, 0);
606
+ const sum = binaryTree.reduce((acc, currentValue, currentKey) => acc + currentKey, 0);
607
607
  expect(sum).toBe(6);
608
608
  });
609
609
 
@@ -625,11 +625,11 @@ describe('BinaryTree iterative methods test', () => {
625
625
 
626
626
  test('should keys', () => {
627
627
  const keys = binaryTree.keys();
628
- expect(keys).toEqual([2, 1, 3]);
628
+ expect([...keys]).toEqual([2, 1, 3]);
629
629
  });
630
630
 
631
631
  test('should values', () => {
632
632
  const values = binaryTree.values();
633
- expect(values).toEqual(['b', 'a', 'c']);
633
+ expect([...values]).toEqual(['b', 'a', 'c']);
634
634
  });
635
635
  });
@@ -864,30 +864,30 @@ describe('BST iterative methods test', () => {
864
864
 
865
865
  test('forEach should iterate over all elements', () => {
866
866
  const mockCallback = jest.fn();
867
- bst.forEach((entry) => {
868
- mockCallback(entry);
867
+ bst.forEach((value, key) => {
868
+ mockCallback(value, key);
869
869
  });
870
870
 
871
871
  expect(mockCallback.mock.calls.length).toBe(3);
872
- expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
873
- expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
874
- expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
872
+ expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
873
+ expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
874
+ expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
875
875
  });
876
876
 
877
877
  test('filter should return a new tree with filtered elements', () => {
878
- const filteredTree = bst.filter(([key]) => key > 1);
878
+ const filteredTree = bst.filter((value, key) => key > 1);
879
879
  expect(filteredTree.size).toBe(2);
880
880
  expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
881
881
  });
882
882
 
883
883
  test('map should return a new tree with modified elements', () => {
884
- const mappedTree = bst.map(([key]) => (key * 2).toString());
884
+ const mappedTree = bst.map((value, key) => (key * 2).toString());
885
885
  expect(mappedTree.size).toBe(3);
886
886
  expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
887
887
  });
888
888
 
889
889
  test('reduce should accumulate values', () => {
890
- const sum = bst.reduce((acc, [key]) => acc + key, 0);
890
+ const sum = bst.reduce((acc, value, key) => acc + key, 0);
891
891
  expect(sum).toBe(6);
892
892
  });
893
893
 
@@ -909,11 +909,11 @@ describe('BST iterative methods test', () => {
909
909
 
910
910
  test('should keys', () => {
911
911
  const keys = bst.keys();
912
- expect(keys).toEqual([1, 2, 3]);
912
+ expect([...keys]).toEqual([1, 2, 3]);
913
913
  });
914
914
 
915
915
  test('should values', () => {
916
916
  const values = bst.values();
917
- expect(values).toEqual(['a', 'b', 'c']);
917
+ expect([...values]).toEqual(['a', 'b', 'c']);
918
918
  });
919
919
  });