stack-typed 1.48.0 → 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 (54) hide show
  1. package/dist/data-structures/base/index.d.ts +1 -0
  2. package/dist/data-structures/base/index.js +17 -0
  3. package/dist/data-structures/base/iterable-base.d.ts +232 -0
  4. package/dist/data-structures/base/iterable-base.js +312 -0
  5. package/dist/data-structures/binary-tree/binary-tree.d.ts +45 -40
  6. package/dist/data-structures/binary-tree/binary-tree.js +91 -88
  7. package/dist/data-structures/binary-tree/tree-multimap.d.ts +12 -0
  8. package/dist/data-structures/binary-tree/tree-multimap.js +16 -0
  9. package/dist/data-structures/graph/abstract-graph.d.ts +44 -6
  10. package/dist/data-structures/graph/abstract-graph.js +50 -27
  11. package/dist/data-structures/hash/hash-map.d.ts +160 -44
  12. package/dist/data-structures/hash/hash-map.js +314 -82
  13. package/dist/data-structures/heap/heap.d.ts +50 -7
  14. package/dist/data-structures/heap/heap.js +60 -30
  15. package/dist/data-structures/index.d.ts +1 -0
  16. package/dist/data-structures/index.js +1 -0
  17. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +38 -51
  18. package/dist/data-structures/linked-list/doubly-linked-list.js +46 -73
  19. package/dist/data-structures/linked-list/singly-linked-list.d.ts +32 -51
  20. package/dist/data-structures/linked-list/singly-linked-list.js +40 -73
  21. package/dist/data-structures/queue/deque.d.ts +29 -51
  22. package/dist/data-structures/queue/deque.js +36 -71
  23. package/dist/data-structures/queue/queue.d.ts +49 -48
  24. package/dist/data-structures/queue/queue.js +69 -82
  25. package/dist/data-structures/stack/stack.d.ts +43 -10
  26. package/dist/data-structures/stack/stack.js +50 -31
  27. package/dist/data-structures/trie/trie.d.ts +41 -6
  28. package/dist/data-structures/trie/trie.js +53 -32
  29. package/dist/types/data-structures/base/base.d.ts +5 -0
  30. package/dist/types/data-structures/base/base.js +2 -0
  31. package/dist/types/data-structures/base/index.d.ts +1 -0
  32. package/dist/types/data-structures/base/index.js +17 -0
  33. package/dist/types/data-structures/hash/hash-map.d.ts +4 -0
  34. package/dist/types/data-structures/index.d.ts +1 -0
  35. package/dist/types/data-structures/index.js +1 -0
  36. package/package.json +2 -2
  37. package/src/data-structures/base/index.ts +1 -0
  38. package/src/data-structures/base/iterable-base.ts +329 -0
  39. package/src/data-structures/binary-tree/binary-tree.ts +98 -93
  40. package/src/data-structures/binary-tree/tree-multimap.ts +18 -0
  41. package/src/data-structures/graph/abstract-graph.ts +55 -28
  42. package/src/data-structures/hash/hash-map.ts +334 -83
  43. package/src/data-structures/heap/heap.ts +63 -36
  44. package/src/data-structures/index.ts +1 -0
  45. package/src/data-structures/linked-list/doubly-linked-list.ts +50 -79
  46. package/src/data-structures/linked-list/singly-linked-list.ts +45 -80
  47. package/src/data-structures/queue/deque.ts +40 -82
  48. package/src/data-structures/queue/queue.ts +72 -87
  49. package/src/data-structures/stack/stack.ts +53 -34
  50. package/src/data-structures/trie/trie.ts +58 -35
  51. package/src/types/data-structures/base/base.ts +6 -0
  52. package/src/types/data-structures/base/index.ts +1 -0
  53. package/src/types/data-structures/hash/hash-map.ts +2 -0
  54. package/src/types/data-structures/index.ts +1 -0
@@ -0,0 +1,329 @@
1
+ import { ElementCallback, PairCallback, ReduceElementCallback, ReducePairCallback } from "../../types";
2
+
3
+ export abstract class IterablePairBase<K = any, V = any> {
4
+
5
+ /**
6
+ * Time Complexity: O(n)
7
+ * Space Complexity: O(1)
8
+ */
9
+
10
+ /**
11
+ * Time Complexity: O(n)
12
+ * Space Complexity: O(1)
13
+ *
14
+ * The function is an implementation of the Symbol.iterator method that returns an iterable iterator.
15
+ * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It
16
+ * allows the function to accept any number of arguments as an array. In this case, the `args`
17
+ * parameter is used to pass any additional arguments to the `_getIterator` method.
18
+ */
19
+ * [Symbol.iterator](...args: any[]): IterableIterator<[K, V]> {
20
+ yield* this._getIterator(...args);
21
+ }
22
+
23
+ /**
24
+ * Time Complexity: O(n)
25
+ * Space Complexity: O(n)
26
+ */
27
+ /**
28
+ * Time Complexity: O(n)
29
+ * Space Complexity: O(n)
30
+ *
31
+ * The function returns an iterator that yields key-value pairs from the object, where the value can
32
+ * be undefined.
33
+ */
34
+ * entries(): IterableIterator<[K, V | undefined]> {
35
+ for (const item of this) {
36
+ yield item;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Time Complexity: O(n)
42
+ * Space Complexity: O(n)
43
+ */
44
+ /**
45
+ * Time Complexity: O(n)
46
+ * Space Complexity: O(n)
47
+ *
48
+ * The function returns an iterator that yields the keys of a data structure.
49
+ */
50
+ * keys(): IterableIterator<K> {
51
+ for (const item of this) {
52
+ yield item[0];
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Time Complexity: O(n)
58
+ * Space Complexity: O(n)
59
+ */
60
+ /**
61
+ * Time Complexity: O(n)
62
+ * Space Complexity: O(n)
63
+ *
64
+ * The function returns an iterator that yields the values of a collection.
65
+ */
66
+ * values(): IterableIterator<V> {
67
+ for (const item of this) {
68
+ yield item[1];
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Time Complexity: O(n)
74
+ * Space Complexity: O(1)
75
+ */
76
+ /**
77
+ * Time Complexity: O(n)
78
+ * Space Complexity: O(1)
79
+ *
80
+ * The `every` function checks if every element in a collection satisfies a given condition.
81
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
82
+ * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is
83
+ * met for the current element in the iteration.
84
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
85
+ * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
86
+ * passed as the first argument to the `predicate` function. If `thisArg` is not provided
87
+ * @returns The `every` method is returning a boolean value. It returns `true` if every element in
88
+ * the collection satisfies the provided predicate function, and `false` otherwise.
89
+ */
90
+ every(predicate: PairCallback<K, V, boolean>, thisArg?: any): boolean {
91
+ let index = 0;
92
+ for (const item of this) {
93
+ if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
94
+ return false;
95
+ }
96
+ }
97
+ return true;
98
+ }
99
+
100
+ /**
101
+ * Time Complexity: O(n)
102
+ * Space Complexity: O(1)
103
+ */
104
+ /**
105
+ * Time Complexity: O(n)
106
+ * Space Complexity: O(1)
107
+ *
108
+ * The "some" function iterates over a collection and returns true if at least one element satisfies
109
+ * a given predicate.
110
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
111
+ * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is
112
+ * met for the current element in the iteration.
113
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
114
+ * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
115
+ * it will be passed as the first argument to the `predicate` function. If `thisArg` is
116
+ * @returns a boolean value. It returns true if the predicate function returns true for any pair in
117
+ * the collection, and false otherwise.
118
+ */
119
+ some(predicate: PairCallback<K, V, boolean>, thisArg?: any): boolean {
120
+ let index = 0;
121
+ for (const item of this) {
122
+ if (predicate.call(thisArg, item[1], item[0], index++, this)) {
123
+ return true;
124
+ }
125
+ }
126
+ return false;
127
+ }
128
+
129
+ /**
130
+ * Time Complexity: O(n)
131
+ * Space Complexity: O(1)
132
+ */
133
+ /**
134
+ * Time Complexity: O(n)
135
+ * Space Complexity: O(1)
136
+ *
137
+ * The `forEach` function iterates over each key-value pair in a collection and executes a callback
138
+ * function for each pair.
139
+ * @param callbackfn - The callback function that will be called for each element in the collection.
140
+ * It takes four parameters: the value of the current element, the key of the current element, the
141
+ * index of the current element, and the collection itself.
142
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
143
+ * specify the value of `this` within the callback function. If `thisArg` is provided, it will be
144
+ * used as the `this` value when calling the callback function. If `thisArg` is not provided, `
145
+ */
146
+ forEach(callbackfn: PairCallback<K, V, void>, thisArg?: any): void {
147
+ let index = 0;
148
+ for (const item of this) {
149
+ const [key, value] = item;
150
+ callbackfn.call(thisArg, value, key, index++, this)
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Time Complexity: O(n)
156
+ * Space Complexity: O(1)
157
+ */
158
+ /**
159
+ * Time Complexity: O(n)
160
+ * Space Complexity: O(1)
161
+ *
162
+ * The `reduce` function iterates over key-value pairs and applies a callback function to each pair,
163
+ * accumulating a single value.
164
+ * @param callbackfn - The callback function that will be called for each element in the collection.
165
+ * It takes four arguments: the current accumulator value, the current value of the element, the key
166
+ * of the element, and the index of the element in the collection. It should return the updated
167
+ * accumulator value.
168
+ * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
169
+ * is the value that will be used as the first argument to the `callbackfn` function when reducing
170
+ * the elements of the collection.
171
+ * @returns The `reduce` method is returning the final value of the accumulator after iterating over
172
+ * all the elements in the collection.
173
+ */
174
+ reduce<U>(callbackfn: ReducePairCallback<K, V, U>, initialValue: U): U {
175
+ let accumulator = initialValue;
176
+ let index = 0;
177
+ for (const item of this) {
178
+ const [key, value] = item;
179
+ accumulator = callbackfn(accumulator, value, key, index++, this)
180
+ }
181
+ return accumulator;
182
+ }
183
+
184
+ protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
185
+ }
186
+
187
+ export abstract class IterableElementBase<V> {
188
+
189
+ /**
190
+ * Time Complexity: O(n)
191
+ * Space Complexity: O(1)
192
+ */
193
+ /**
194
+ * Time Complexity: O(n)
195
+ * Space Complexity: O(1)
196
+ *
197
+ * The function is an implementation of the Symbol.iterator method that returns an IterableIterator.
198
+ * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It
199
+ * allows the function to accept any number of arguments as an array. In this case, the `args`
200
+ * parameter is used to pass any number of arguments to the `_getIterator` method.
201
+ */
202
+ * [Symbol.iterator](...args: any[]): IterableIterator<V> {
203
+ yield* this._getIterator(...args);
204
+ }
205
+
206
+ /**
207
+ * Time Complexity: O(n)
208
+ * Space Complexity: O(n)
209
+ */
210
+ /**
211
+ * Time Complexity: O(n)
212
+ * Space Complexity: O(n)
213
+ *
214
+ * The function returns an iterator that yields all the values in the object.
215
+ */
216
+ * values(): IterableIterator<V> {
217
+ for (const item of this) {
218
+ yield item;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Time Complexity: O(n)
224
+ * Space Complexity: O(1)
225
+ */
226
+ /**
227
+ * Time Complexity: O(n)
228
+ * Space Complexity: O(1)
229
+ *
230
+ * The `every` function checks if every element in the array satisfies a given predicate.
231
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
232
+ * the current element being processed, its index, and the array it belongs to. It should return a
233
+ * boolean value indicating whether the element satisfies a certain condition or not.
234
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
235
+ * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
236
+ * passed as the `this` value to the `predicate` function. If `thisArg` is
237
+ * @returns The `every` method is returning a boolean value. It returns `true` if every element in
238
+ * the array satisfies the provided predicate function, and `false` otherwise.
239
+ */
240
+ every(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
241
+ let index = 0;
242
+ for (const item of this) {
243
+ if (!predicate.call(thisArg, item as V, index++, this)) {
244
+ return false;
245
+ }
246
+ }
247
+ return true;
248
+ }
249
+
250
+ /**
251
+ * Time Complexity: O(n)
252
+ * Space Complexity: O(1)
253
+ */
254
+ /**
255
+ * Time Complexity: O(n)
256
+ * Space Complexity: O(1)
257
+ *
258
+ * The "some" function checks if at least one element in a collection satisfies a given predicate.
259
+ * @param predicate - The `predicate` parameter is a callback function that takes three arguments:
260
+ * `value`, `index`, and `array`. It should return a boolean value indicating whether the current
261
+ * element satisfies the condition.
262
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
263
+ * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
264
+ * it will be passed as the `this` value to the `predicate` function. If `thisArg
265
+ * @returns a boolean value. It returns true if the predicate function returns true for any element
266
+ * in the collection, and false otherwise.
267
+ */
268
+ some(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
269
+ let index = 0;
270
+ for (const item of this) {
271
+ if (predicate.call(thisArg, item as V, index++, this)) {
272
+ return true;
273
+ }
274
+ }
275
+ return false;
276
+ }
277
+
278
+ /**
279
+ * Time Complexity: O(n)
280
+ * Space Complexity: O(1)
281
+ */
282
+ /**
283
+ * Time Complexity: O(n)
284
+ * Space Complexity: O(1)
285
+ *
286
+ * The `forEach` function iterates over each element in an array-like object and calls a callback
287
+ * function for each element.
288
+ * @param callbackfn - The callbackfn parameter is a function that will be called for each element in
289
+ * the array. It takes three arguments: the current element being processed, the index of the current
290
+ * element, and the array that forEach was called upon.
291
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
292
+ * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
293
+ * be passed as the `this` value to the `callbackfn` function. If `thisArg
294
+ */
295
+ forEach(callbackfn: ElementCallback<V, void>, thisArg?: any): void {
296
+ let index = 0;
297
+ for (const item of this) {
298
+ callbackfn.call(thisArg, item as V, index++, this)
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Time Complexity: O(n)
304
+ * Space Complexity: O(1)
305
+ */
306
+ /**
307
+ * Time Complexity: O(n)
308
+ * Space Complexity: O(1)
309
+ *
310
+ * The `reduce` function iterates over the elements of an array-like object and applies a callback
311
+ * function to reduce them into a single value.
312
+ * @param callbackfn - The callbackfn parameter is a function that will be called for each element in
313
+ * the array. It takes four arguments:
314
+ * @param {U} initialValue - The initialValue parameter is the initial value of the accumulator. It
315
+ * is the value that the accumulator starts with before the reduction operation begins.
316
+ * @returns The `reduce` method is returning the final value of the accumulator after iterating over
317
+ * all the elements in the array and applying the callback function to each element.
318
+ */
319
+ reduce<U>(callbackfn: ReduceElementCallback<V, U>, initialValue: U): U {
320
+ let accumulator = initialValue;
321
+ let index = 0;
322
+ for (const item of this) {
323
+ accumulator = callbackfn(accumulator, item as V, index++, this)
324
+ }
325
+ return accumulator;
326
+ }
327
+
328
+ protected abstract _getIterator(...args: any[]): IterableIterator<V>;
329
+ }
@@ -13,7 +13,7 @@ import type {
13
13
  BTNKey,
14
14
  BTNodeEntry,
15
15
  BTNodeExemplar,
16
- BTNodeKeyOrNode
16
+ BTNodeKeyOrNode,
17
17
  } from '../../types';
18
18
  import {
19
19
  BinaryTreeNested,
@@ -22,11 +22,13 @@ import {
22
22
  DFSOrderPattern,
23
23
  FamilyPosition,
24
24
  IterationType,
25
- NodeDisplayLayout
25
+ NodeDisplayLayout,
26
+ PairCallback
26
27
  } from '../../types';
27
28
  import { IBinaryTree } from '../../interfaces';
28
29
  import { trampoline } from '../../utils';
29
30
  import { Queue } from '../queue';
31
+ import { IterablePairBase } from "../base";
30
32
 
31
33
  /**
32
34
  * Represents a node in a binary tree.
@@ -102,9 +104,10 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
102
104
  * 8. Full Trees: Every node has either 0 or 2 children.
103
105
  * 9. Complete Trees: All levels are fully filled except possibly the last, filled from left to right.
104
106
  */
105
- export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
106
- implements IBinaryTree<V, N, TREE> {
107
107
 
108
+ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>> extends IterablePairBase<BTNKey, V | undefined>
109
+
110
+ implements IBinaryTree<V, N, TREE> {
108
111
  iterationType = IterationType.ITERATIVE
109
112
 
110
113
  /**
@@ -117,7 +120,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
117
120
  * required.
118
121
  */
119
122
  constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BinaryTreeOptions>) {
120
-
123
+ super();
121
124
  if (options) {
122
125
  const { iterationType } = options;
123
126
  if (iterationType) {
@@ -1725,33 +1728,48 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1725
1728
 
1726
1729
  /**
1727
1730
  * Time complexity: O(n)
1728
- * Space complexity: O(1)
1731
+ * Space complexity: O(n)
1729
1732
  */
1730
1733
 
1731
1734
  /**
1732
- * The `forEach` function iterates over each entry in a tree and calls a callback function with the
1733
- * entry and the tree as arguments.
1734
- * @param callback - The callback parameter is a function that will be called for each entry in the
1735
- * tree. It takes two parameters: entry and tree.
1736
- */
1737
- forEach(callback: (entry: [BTNKey, V | undefined], tree: this) => void): void {
1738
- for (const entry of this) {
1739
- callback(entry, this);
1740
- }
1735
+ * Time complexity: O(n)
1736
+ * Space complexity: O(n)
1737
+ *
1738
+ * The `clone` function creates a new tree object and copies all the nodes from the original tree to
1739
+ * the new tree.
1740
+ * @returns The `clone()` method is returning a cloned instance of the `TREE` object.
1741
+ */
1742
+ clone(): TREE {
1743
+ const cloned = this.createTree();
1744
+ this.bfs(node => cloned.add([node.key, node.value]));
1745
+ return cloned;
1741
1746
  }
1742
1747
 
1743
1748
  /**
1744
- * The `filter` function creates a new tree by iterating over the entries of the current tree and
1745
- * adding the entries that satisfy the given predicate.
1746
- * @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
1747
- * `tree`.
1748
- * @returns The `filter` method is returning a new tree object that contains only the entries that
1749
- * satisfy the given predicate function.
1749
+ * Time Complexity: O(n)
1750
+ * Space Complexity: O(n)
1750
1751
  */
1751
- filter(predicate: (entry: [BTNKey, V | undefined], tree: this) => boolean) {
1752
+
1753
+ /**
1754
+ * Time Complexity: O(n)
1755
+ * Space Complexity: O(n)
1756
+ *
1757
+ * The `filter` function creates a new tree by iterating over the elements of the current tree and
1758
+ * adding only the elements that satisfy the given predicate function.
1759
+ * @param predicate - The `predicate` parameter is a function that takes three arguments: `value`,
1760
+ * `key`, and `index`. It should return a boolean value indicating whether the pair should be
1761
+ * included in the filtered tree or not.
1762
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
1763
+ * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
1764
+ * it will be passed as the first argument to the `predicate` function. If `thisArg` is
1765
+ * @returns The `filter` method is returning a new tree object that contains the key-value pairs that
1766
+ * pass the given predicate function.
1767
+ */
1768
+ filter(predicate: PairCallback<BTNKey, V | undefined, boolean>, thisArg?: any) {
1752
1769
  const newTree = this.createTree();
1770
+ let index = 0;
1753
1771
  for (const [key, value] of this) {
1754
- if (predicate([key, value], this)) {
1772
+ if (predicate.call(thisArg, value, key, index++, this)) {
1755
1773
  newTree.add([key, value]);
1756
1774
  }
1757
1775
  }
@@ -1759,58 +1777,74 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1759
1777
  }
1760
1778
 
1761
1779
  /**
1762
- * The `map` function creates a new tree by applying a callback function to each entry in the current
1763
- * tree.
1764
- * @param callback - The callback parameter is a function that takes two arguments: entry and tree.
1780
+ * Time Complexity: O(n)
1781
+ * Space Complexity: O(n)
1782
+ */
1783
+
1784
+ /**
1785
+ * Time Complexity: O(n)
1786
+ * Space Complexity: O(n)
1787
+ *
1788
+ * The `map` function creates a new tree by applying a callback function to each key-value pair in
1789
+ * the original tree.
1790
+ * @param callback - The callback parameter is a function that will be called for each key-value pair
1791
+ * in the tree. It takes four arguments: the value of the current pair, the key of the current pair,
1792
+ * the index of the current pair, and a reference to the tree itself. The callback function should
1793
+ * return a new
1794
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
1795
+ * specify the value of `this` within the callback function. If you pass a value for `thisArg`, it
1796
+ * will be used as the `this` value when the callback function is called. If you don't pass a value
1765
1797
  * @returns The `map` method is returning a new tree object.
1766
1798
  */
1767
- map(callback: (entry: [BTNKey, V | undefined], tree: this) => V) {
1799
+ map(callback: PairCallback<BTNKey, V | undefined, V>, thisArg?: any) {
1768
1800
  const newTree = this.createTree();
1801
+ let index = 0;
1769
1802
  for (const [key, value] of this) {
1770
- newTree.add([key, callback([key, value], this)]);
1803
+ newTree.add([key, callback.call(thisArg, value, key, index++, this)]);
1771
1804
  }
1772
1805
  return newTree;
1773
1806
  }
1774
1807
 
1775
- // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1776
- // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1777
- // const newTree = this.createTree();
1778
- // for (const [key, value] of this) {
1779
- // newTree.add(key, callback([key, value], this));
1780
- // }
1781
- // return newTree;
1782
- // }
1783
-
1784
- /**
1785
- * The `reduce` function iterates over the entries of a tree and applies a callback function to each
1786
- * entry, accumulating a single value.
1787
- * @param callback - The callback parameter is a function that takes three arguments: accumulator,
1788
- * entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
1789
- * based on the logic defined in the callback function.
1790
- * @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
1791
- * is the value that will be passed as the first argument to the callback function when reducing the
1792
- * elements of the tree.
1793
- * @returns The `reduce` method is returning the final value of the accumulator after iterating over
1794
- * all the entries in the tree and applying the callback function to each entry.
1795
- */
1796
- reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: this) => T, initialValue: T): T {
1797
- let accumulator = initialValue;
1798
- for (const [key, value] of this) {
1799
- accumulator = callback(accumulator, [key, value], this);
1800
- }
1801
- return accumulator;
1802
- }
1808
+ // // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1809
+ // // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1810
+ // // const newTree = this.createTree();
1811
+ // // for (const [key, value] of this) {
1812
+ // // newTree.add(key, callback([key, value], this));
1813
+ // // }
1814
+ // // return newTree;
1815
+ // // }
1816
+ //
1803
1817
 
1804
1818
  /**
1805
- * The above function is an iterator for a binary tree that can be used to traverse the tree in
1806
- * either an iterative or recursive manner.
1807
- * @param node - The `node` parameter represents the current node in the binary tree from which the
1808
- * iteration starts. It is an optional parameter with a default value of `this.root`, which means
1809
- * that if no node is provided, the iteration will start from the root of the binary tree.
1810
- * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
1811
- * binary tree nodes in a specific order.
1819
+ * The `print` function is used to display a binary tree structure in a visually appealing way.
1820
+ * @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
1821
+ * undefined`. It represents the root node of a binary tree. The root node can have one of the
1822
+ * following types:
1823
+ * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
1812
1824
  */
1813
- * [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
1825
+ print(beginRoot: BTNodeKeyOrNode<N> = this.root, options?: BinaryTreePrintOptions): void {
1826
+ const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1827
+ beginRoot = this.ensureNode(beginRoot);
1828
+ if (!beginRoot) return;
1829
+
1830
+ if (opts.isShowUndefined) console.log(`U for undefined
1831
+ `);
1832
+ if (opts.isShowNull) console.log(`N for null
1833
+ `);
1834
+ if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
1835
+ `);
1836
+
1837
+ const display = (root: N | null | undefined): void => {
1838
+ const [lines, , ,] = this._displayAux(root, opts);
1839
+ for (const line of lines) {
1840
+ console.log(line);
1841
+ }
1842
+ };
1843
+
1844
+ display(beginRoot);
1845
+ }
1846
+
1847
+ protected* _getIterator(node = this.root): IterableIterator<[BTNKey, V | undefined]> {
1814
1848
  if (!node) return;
1815
1849
 
1816
1850
  if (this.iterationType === IterationType.ITERATIVE) {
@@ -1841,35 +1875,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1841
1875
  }
1842
1876
  }
1843
1877
 
1844
- /**
1845
- * The `print` function is used to display a binary tree structure in a visually appealing way.
1846
- * @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
1847
- * undefined`. It represents the root node of a binary tree. The root node can have one of the
1848
- * following types:
1849
- * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
1850
- */
1851
- print(beginRoot: BTNodeKeyOrNode<N> = this.root, options?: BinaryTreePrintOptions): void {
1852
- const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1853
- beginRoot = this.ensureNode(beginRoot);
1854
- if (!beginRoot) return;
1855
-
1856
- if (opts.isShowUndefined) console.log(`U for undefined
1857
- `);
1858
- if (opts.isShowNull) console.log(`N for null
1859
- `);
1860
- if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
1861
- `);
1862
-
1863
- const display = (root: N | null | undefined): void => {
1864
- const [lines, , ,] = this._displayAux(root, opts);
1865
- for (const line of lines) {
1866
- console.log(line);
1867
- }
1868
- };
1869
-
1870
- display(beginRoot);
1871
- }
1872
-
1873
1878
  protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
1874
1879
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
1875
1880
  const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
@@ -318,6 +318,24 @@ export class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultim
318
318
  this._count = 0;
319
319
  }
320
320
 
321
+ /**
322
+ * Time complexity: O(n)
323
+ * Space complexity: O(n)
324
+ */
325
+
326
+ /**
327
+ * Time complexity: O(n)
328
+ * Space complexity: O(n)
329
+ *
330
+ * The `clone` function creates a deep copy of a tree object.
331
+ * @returns The `clone()` method is returning a cloned instance of the `TREE` object.
332
+ */
333
+ override clone(): TREE {
334
+ const cloned = this.createTree();
335
+ this.bfs(node => cloned.add([node.key, node.value], node.count));
336
+ return cloned;
337
+ }
338
+
321
339
  /**
322
340
  * Time Complexity: O(1) - constant time, as it performs basic pointer assignments.
323
341
  * Space Complexity: O(1) - constant space, as it only uses a constant amount of memory.