directed-graph-typed 1.48.0 → 1.49.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 (89) 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/avl-tree.d.ts +28 -19
  6. package/dist/data-structures/binary-tree/avl-tree.js +22 -11
  7. package/dist/data-structures/binary-tree/binary-tree.d.ts +158 -152
  8. package/dist/data-structures/binary-tree/binary-tree.js +241 -215
  9. package/dist/data-structures/binary-tree/bst.d.ts +64 -48
  10. package/dist/data-structures/binary-tree/bst.js +94 -65
  11. package/dist/data-structures/binary-tree/rb-tree.d.ts +39 -39
  12. package/dist/data-structures/binary-tree/rb-tree.js +42 -49
  13. package/dist/data-structures/binary-tree/tree-multimap.d.ts +60 -34
  14. package/dist/data-structures/binary-tree/tree-multimap.js +59 -27
  15. package/dist/data-structures/graph/abstract-graph.d.ts +92 -53
  16. package/dist/data-structures/graph/abstract-graph.js +130 -103
  17. package/dist/data-structures/graph/directed-graph.d.ts +70 -52
  18. package/dist/data-structures/graph/directed-graph.js +111 -65
  19. package/dist/data-structures/graph/map-graph.d.ts +5 -5
  20. package/dist/data-structures/graph/map-graph.js +8 -8
  21. package/dist/data-structures/graph/undirected-graph.d.ts +51 -32
  22. package/dist/data-structures/graph/undirected-graph.js +117 -54
  23. package/dist/data-structures/hash/hash-map.d.ts +160 -44
  24. package/dist/data-structures/hash/hash-map.js +314 -82
  25. package/dist/data-structures/heap/heap.d.ts +50 -7
  26. package/dist/data-structures/heap/heap.js +60 -30
  27. package/dist/data-structures/index.d.ts +1 -0
  28. package/dist/data-structures/index.js +1 -0
  29. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +42 -55
  30. package/dist/data-structures/linked-list/doubly-linked-list.js +50 -77
  31. package/dist/data-structures/linked-list/singly-linked-list.d.ts +36 -55
  32. package/dist/data-structures/linked-list/singly-linked-list.js +44 -77
  33. package/dist/data-structures/queue/deque.d.ts +35 -167
  34. package/dist/data-structures/queue/deque.js +43 -249
  35. package/dist/data-structures/queue/queue.d.ts +49 -48
  36. package/dist/data-structures/queue/queue.js +69 -82
  37. package/dist/data-structures/stack/stack.d.ts +43 -10
  38. package/dist/data-structures/stack/stack.js +50 -31
  39. package/dist/data-structures/trie/trie.d.ts +41 -6
  40. package/dist/data-structures/trie/trie.js +53 -32
  41. package/dist/interfaces/binary-tree.d.ts +6 -6
  42. package/dist/types/common.d.ts +11 -8
  43. package/dist/types/common.js +6 -1
  44. package/dist/types/data-structures/base/base.d.ts +5 -0
  45. package/dist/types/data-structures/base/base.js +2 -0
  46. package/dist/types/data-structures/base/index.d.ts +1 -0
  47. package/dist/types/data-structures/base/index.js +17 -0
  48. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +3 -3
  49. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +4 -4
  50. package/dist/types/data-structures/binary-tree/bst.d.ts +6 -6
  51. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +3 -3
  52. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +3 -3
  53. package/dist/types/data-structures/hash/hash-map.d.ts +4 -0
  54. package/dist/types/data-structures/index.d.ts +1 -0
  55. package/dist/types/data-structures/index.js +1 -0
  56. package/package.json +2 -2
  57. package/src/data-structures/base/index.ts +1 -0
  58. package/src/data-structures/base/iterable-base.ts +329 -0
  59. package/src/data-structures/binary-tree/avl-tree.ts +37 -25
  60. package/src/data-structures/binary-tree/binary-tree.ts +336 -296
  61. package/src/data-structures/binary-tree/bst.ts +135 -89
  62. package/src/data-structures/binary-tree/rb-tree.ts +60 -69
  63. package/src/data-structures/binary-tree/tree-multimap.ts +86 -49
  64. package/src/data-structures/graph/abstract-graph.ts +136 -104
  65. package/src/data-structures/graph/directed-graph.ts +114 -65
  66. package/src/data-structures/graph/map-graph.ts +8 -8
  67. package/src/data-structures/graph/undirected-graph.ts +124 -56
  68. package/src/data-structures/hash/hash-map.ts +335 -84
  69. package/src/data-structures/heap/heap.ts +63 -36
  70. package/src/data-structures/index.ts +1 -0
  71. package/src/data-structures/linked-list/doubly-linked-list.ts +54 -83
  72. package/src/data-structures/linked-list/singly-linked-list.ts +49 -84
  73. package/src/data-structures/queue/deque.ts +43 -275
  74. package/src/data-structures/queue/queue.ts +71 -86
  75. package/src/data-structures/stack/stack.ts +53 -34
  76. package/src/data-structures/trie/trie.ts +58 -35
  77. package/src/interfaces/binary-tree.ts +5 -6
  78. package/src/types/common.ts +11 -8
  79. package/src/types/data-structures/base/base.ts +6 -0
  80. package/src/types/data-structures/base/index.ts +1 -0
  81. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -3
  82. package/src/types/data-structures/binary-tree/binary-tree.ts +6 -5
  83. package/src/types/data-structures/binary-tree/bst.ts +6 -6
  84. package/src/types/data-structures/binary-tree/rb-tree.ts +3 -3
  85. package/src/types/data-structures/binary-tree/tree-multimap.ts +3 -3
  86. package/src/types/data-structures/hash/hash-map.ts +2 -0
  87. package/src/types/data-structures/heap/heap.ts +1 -1
  88. package/src/types/data-structures/index.ts +1 -0
  89. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -1
@@ -7,9 +7,248 @@
7
7
  */
8
8
 
9
9
  import { isWeakKey, rangeCheck } from '../../utils';
10
- import { HashMapLinkedNode, HashMapOptions } from '../../types';
10
+ import { EntryCallback, HashMapLinkedNode, HashMapOptions, HashMapStoreItem } from '../../types';
11
+ import { IterableEntryBase } from "../base";
11
12
 
12
- export class HashMap<K = any, V = any> {
13
+ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
14
+ protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};
15
+ protected _objMap: Map<object, V> = new Map();
16
+
17
+ /**
18
+ * The constructor function initializes a new instance of a class with optional elements and options.
19
+ * @param elements - The `elements` parameter is an iterable containing key-value pairs `[K, V]`. It
20
+ * is optional and defaults to an empty array `[]`. This parameter is used to initialize the map with
21
+ * key-value pairs.
22
+ * @param [options] - The `options` parameter is an optional object that can contain additional
23
+ * configuration options for the constructor. In this case, it has one property:
24
+ */
25
+ constructor(elements: Iterable<[K, V]> = [], options?: {
26
+ hashFn: (key: K) => string
27
+ }) {
28
+ super();
29
+ if (options) {
30
+ const { hashFn } = options;
31
+ if (hashFn) {
32
+ this._hashFn = hashFn;
33
+
34
+ }
35
+ }
36
+ if (elements) {
37
+ this.setMany(elements);
38
+ }
39
+ }
40
+
41
+ protected _size = 0;
42
+
43
+ get size(): number {
44
+ return this._size;
45
+ }
46
+
47
+ isEmpty(): boolean {
48
+ return this.size === 0;
49
+ }
50
+
51
+ clear() {
52
+ this._store = {};
53
+ this._objMap.clear();
54
+ this._size = 0;
55
+ }
56
+
57
+ /**
58
+ * The `set` function adds a key-value pair to a map-like data structure, incrementing the size if
59
+ * the key is not already present.
60
+ * @param {K} key - The key parameter is the key used to identify the value in the data structure. It
61
+ * can be of any type, but if it is an object, it will be stored in a Map, otherwise it will be
62
+ * stored in a regular JavaScript object.
63
+ * @param {V} value - The value parameter represents the value that you want to associate with the
64
+ * key in the data structure.
65
+ */
66
+ set(key: K, value: V) {
67
+
68
+ if (this._isObjKey(key)) {
69
+ if (!this._objMap.has(key)) {
70
+ this._size++;
71
+ }
72
+ this._objMap.set(key, value);
73
+
74
+ } else {
75
+ const strKey = this._getNoObjKey(key);
76
+ if (this._store[strKey] === undefined) {
77
+ this._size++;
78
+ }
79
+ this._store[strKey] = { key, value };
80
+ }
81
+ }
82
+
83
+ /**
84
+ * The function "setMany" sets multiple key-value pairs in a map.
85
+ * @param elements - The `elements` parameter is an iterable containing key-value pairs. Each
86
+ * key-value pair is represented as an array with two elements: the key and the value.
87
+ */
88
+ setMany(elements: Iterable<[K, V]>) {
89
+ for (const [key, value] of elements) this.set(key, value);
90
+ }
91
+
92
+ /**
93
+ * The `get` function retrieves a value from a map based on a given key, either from an object map or
94
+ * a string map.
95
+ * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
96
+ * of any type, but it should be compatible with the key type used when the map was created.
97
+ * @returns The method `get(key: K)` returns a value of type `V` if the key exists in the `_objMap`
98
+ * or `_store`, otherwise it returns `undefined`.
99
+ */
100
+ get(key: K): V | undefined {
101
+ if (this._isObjKey(key)) {
102
+ return this._objMap.get(key);
103
+ } else {
104
+ const strKey = this._getNoObjKey(key);
105
+ return this._store[strKey]?.value;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * The `has` function checks if a given key exists in the `_objMap` or `_store` based on whether it
111
+ * is an object key or not.
112
+ * @param {K} key - The parameter "key" is of type K, which means it can be any type.
113
+ * @returns The `has` method is returning a boolean value.
114
+ */
115
+ has(key: K): boolean {
116
+ if (this._isObjKey(key)) {
117
+ return this._objMap.has(key);
118
+ } else {
119
+ const strKey = this._getNoObjKey(key);
120
+ return strKey in this._store;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * The `delete` function removes an element from a map-like data structure based on the provided key.
126
+ * @param {K} key - The `key` parameter is the key of the element that you want to delete from the
127
+ * data structure.
128
+ * @returns The `delete` method returns a boolean value. It returns `true` if the key was
129
+ * successfully deleted from the map, and `false` if the key was not found in the map.
130
+ */
131
+ delete(key: K): boolean {
132
+ if (this._isObjKey(key)) {
133
+ if (this._objMap.has(key)) {
134
+ this._size--
135
+ }
136
+
137
+ return this._objMap.delete(key);
138
+ } else {
139
+ const strKey = this._getNoObjKey(key);
140
+ if (strKey in this._store) {
141
+ delete this._store[strKey];
142
+ this._size--;
143
+ return true;
144
+ }
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Time Complexity: O(n)
151
+ * Space Complexity: O(n)
152
+ */
153
+
154
+ /**
155
+ * Time Complexity: O(n)
156
+ * Space Complexity: O(n)
157
+ *
158
+ * The `map` function in TypeScript creates a new HashMap by applying a callback function to each
159
+ * key-value pair in the original HashMap.
160
+ * @param callbackfn - The callback function that will be called for each key-value pair in the
161
+ * HashMap. It takes four parameters:
162
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
163
+ * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
164
+ * be passed as the `this` value to the `callbackfn` function. If `thisArg
165
+ * @returns The `map` method is returning a new `HashMap` object with the transformed values based on
166
+ * the provided callback function.
167
+ */
168
+ map<U>(callbackfn: EntryCallback<K, V, U>, thisArg?: any): HashMap<K, U> {
169
+ const resultMap = new HashMap<K, U>();
170
+ let index = 0;
171
+ for (const [key, value] of this) {
172
+ resultMap.set(key, callbackfn.call(thisArg, value, key, index++, this));
173
+ }
174
+ return resultMap;
175
+ }
176
+
177
+ /**
178
+ * Time Complexity: O(n)
179
+ * Space Complexity: O(n)
180
+ */
181
+
182
+ /**
183
+ * Time Complexity: O(n)
184
+ * Space Complexity: O(n)
185
+ *
186
+ * The `filter` function creates a new HashMap containing key-value pairs from the original HashMap
187
+ * that satisfy a given predicate function.
188
+ * @param predicate - The predicate parameter is a function that takes four arguments: value, key,
189
+ * index, and map. It is used to determine whether an element should be included in the filtered map
190
+ * or not. The function should return a boolean value - true if the element should be included, and
191
+ * false otherwise.
192
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
193
+ * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
194
+ * passed as the `this` value to the `predicate` function. If `thisArg` is
195
+ * @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs
196
+ * from the original `HashMap` that pass the provided `predicate` function.
197
+ */
198
+ filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): HashMap<K, V> {
199
+ const filteredMap = new HashMap<K, V>();
200
+ let index = 0;
201
+ for (const [key, value] of this) {
202
+ if (predicate.call(thisArg, value, key, index++, this)) {
203
+ filteredMap.set(key, value);
204
+ }
205
+ }
206
+ return filteredMap;
207
+ }
208
+
209
+ print(): void {
210
+ console.log([...this.entries()]);
211
+ }
212
+
213
+ /**
214
+ * The function returns an iterator that yields key-value pairs from both an object store and an
215
+ * object map.
216
+ */
217
+ protected* _getIterator(): IterableIterator<[K, V]> {
218
+ for (const node of Object.values(this._store)) {
219
+ yield [node.key, node.value] as [K, V];
220
+ }
221
+ for (const node of this._objMap) {
222
+ yield node as [K, V];
223
+ }
224
+ }
225
+
226
+ protected _hashFn: (key: K) => string = (key: K) => String(key);
227
+
228
+ protected _isObjKey(key: any): key is (object | ((...args: any[]) => any)) {
229
+ const keyType = typeof key;
230
+ return (keyType === 'object' || keyType === 'function') && key !== null
231
+ }
232
+
233
+ protected _getNoObjKey(key: K): string {
234
+ const keyType = typeof key;
235
+
236
+ let strKey: string;
237
+ if (keyType !== "string" && keyType !== "number" && keyType !== "symbol") {
238
+ strKey = this._hashFn(key);
239
+ } else {
240
+ if (keyType === "number") {
241
+ // TODO numeric key should has its own hash
242
+ strKey = <string>key;
243
+ } else {
244
+ strKey = <string>key;
245
+ }
246
+ }
247
+ return strKey;
248
+ }
249
+ }
250
+
251
+ export class LinkedHashMap<K = any, V = any> extends IterableEntryBase<K, V> {
13
252
 
14
253
  protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};
15
254
  protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();
@@ -25,6 +264,7 @@ export class HashMap<K = any, V = any> {
25
264
  hashFn: (key: K) => String(key),
26
265
  objHashFn: (key: K) => (<object>key)
27
266
  }) {
267
+ super();
28
268
  this._sentinel = <HashMapLinkedNode<K, V>>{};
29
269
  this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
30
270
 
@@ -108,49 +348,64 @@ export class HashMap<K = any, V = any> {
108
348
  */
109
349
  set(key: K, value?: V) {
110
350
  let node;
351
+ const isNewKey = !this.has(key); // Check if the key is new
111
352
 
112
353
  if (isWeakKey(key)) {
113
354
  const hash = this._objHashFn(key);
114
355
  node = this._objMap.get(hash);
115
356
 
116
- if (node) {
117
- // If the node already exists, update its value
118
- node.value = value;
119
- } else {
357
+ if (!node && isNewKey) {
120
358
  // Create new node
121
359
  node = { key: <K>hash, value, prev: this._tail, next: this._sentinel };
122
-
123
- // Add new nodes to _objMap and linked list
124
360
  this._objMap.set(hash, node);
361
+ } else if (node) {
362
+ // Update the value of an existing node
363
+ node.value = value;
125
364
  }
126
365
  } else {
127
366
  const hash = this._hashFn(key);
128
- // Non-object keys are handled in the same way as the original implementation
129
367
  node = this._noObjMap[hash];
130
- if (node) {
368
+
369
+ if (!node && isNewKey) {
370
+ this._noObjMap[hash] = node = { key, value, prev: this._tail, next: this._sentinel };
371
+ } else if (node) {
372
+ // Update the value of an existing node
131
373
  node.value = value;
374
+ }
375
+ }
376
+
377
+ if (node && isNewKey) {
378
+ // Update the head and tail of the linked list
379
+ if (this._size === 0) {
380
+ this._head = node;
381
+ this._sentinel.next = node;
132
382
  } else {
133
- this._noObjMap[hash] = node = {
134
- key,
135
- value,
136
- prev: this._tail,
137
- next: this._sentinel
138
- };
383
+ this._tail.next = node;
384
+ node.prev = this._tail; // Make sure that the prev of the new node points to the current tail node
139
385
  }
386
+ this._tail = node;
387
+ this._sentinel.prev = node;
388
+ this._size++;
140
389
  }
141
390
 
142
- if (this._size === 0) {
143
- this._head = node;
144
- this._sentinel.next = node;
391
+ return this._size;
392
+ }
393
+
394
+ has(key: K): boolean {
395
+ if (isWeakKey(key)) {
396
+ const hash = this._objHashFn(key);
397
+ return this._objMap.has(hash);
145
398
  } else {
146
- this._tail.next = node;
399
+ const hash = this._hashFn(key);
400
+ return hash in this._noObjMap;
147
401
  }
402
+ }
148
403
 
149
- this._tail = node;
150
- this._sentinel.prev = node;
151
- this._size++;
152
-
153
- return this._size;
404
+ setMany(entries: Iterable<[K, V]>): void {
405
+ for (const entry of entries) {
406
+ const [key, value] = entry;
407
+ this.set(key, value);
408
+ }
154
409
  }
155
410
 
156
411
  /**
@@ -283,37 +538,40 @@ export class HashMap<K = any, V = any> {
283
538
  this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
284
539
  }
285
540
 
286
- /**
287
- * Time Complexity: O(n), where n is the number of elements in the HashMap.
288
- * Space Complexity: O(1)
289
- *
290
- * The `forEach` function iterates over each element in a HashMap and executes a callback function on
291
- * each element.
292
- * @param callback - The callback parameter is a function that will be called for each element in the
293
- * HashMap. It takes three arguments:
294
- */
295
- forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void) {
296
- let index = 0;
297
- let node = this._head;
298
- while (node !== this._sentinel) {
299
- callback(<[K, V]>[node.key, node.value], index++, this);
300
- node = node.next;
541
+ clone(): LinkedHashMap<K, V> {
542
+ const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });
543
+ for (const entry of this) {
544
+ const [key, value] = entry;
545
+ cloned.set(key, value);
301
546
  }
547
+ return cloned;
302
548
  }
303
549
 
304
550
  /**
305
- * The `filter` function takes a predicate function and returns a new HashMap containing only the
306
- * key-value pairs that satisfy the predicate.
307
- * @param predicate - The `predicate` parameter is a function that takes two arguments: `element` and
308
- * `map`.
309
- * @returns a new HashMap object that contains the key-value pairs from the original HashMap that
310
- * satisfy the given predicate function.
551
+ * Time Complexity: O(n)
552
+ * Space Complexity: O(n)
311
553
  */
312
- filter(predicate: (element: [K, V], index: number, map: HashMap<K, V>) => boolean): HashMap<K, V> {
313
- const filteredMap = new HashMap<K, V>();
554
+
555
+ /**
556
+ * Time Complexity: O(n)
557
+ * Space Complexity: O(n)
558
+ *
559
+ * The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original
560
+ * map that satisfy a given predicate function.
561
+ * @param predicate - The `predicate` parameter is a callback function that takes four arguments:
562
+ * `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the
563
+ * current element should be included in the filtered map or not.
564
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
565
+ * specify the value of `this` within the `predicate` function. It is used when you want to bind a
566
+ * specific object as the context for the `predicate` function. If `thisArg` is not provided, `this
567
+ * @returns a new `LinkedHashMap` object that contains the key-value pairs from the original
568
+ * `LinkedHashMap` object that satisfy the given predicate function.
569
+ */
570
+ filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): LinkedHashMap<K, V> {
571
+ const filteredMap = new LinkedHashMap<K, V>();
314
572
  let index = 0;
315
573
  for (const [key, value] of this) {
316
- if (predicate([key, value], index, this)) {
574
+ if (predicate.call(thisArg, value, key, index, this)) {
317
575
  filteredMap.set(key, value);
318
576
  }
319
577
  index++;
@@ -322,63 +580,56 @@ export class HashMap<K = any, V = any> {
322
580
  }
323
581
 
324
582
  /**
325
- * The `map` function takes a callback function and returns a new HashMap with the values transformed
326
- * by the callback.
327
- * @param callback - The `callback` parameter is a function that takes two arguments: `element` and
328
- * `map`.
329
- * @returns a new HashMap object with the values mapped according to the provided callback function.
583
+ * Time Complexity: O(n)
584
+ * Space Complexity: O(n)
585
+ */
586
+
587
+ /**
588
+ * Time Complexity: O(n)
589
+ * Space Complexity: O(n)
590
+ *
591
+ * The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to
592
+ * each key-value pair in the original map.
593
+ * @param callback - The callback parameter is a function that will be called for each key-value pair
594
+ * in the map. It takes four arguments: the value of the current key-value pair, the key of the
595
+ * current key-value pair, the index of the current key-value pair, and the map itself. The callback
596
+ * function should
597
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
598
+ * specify the value of `this` within the callback function. If provided, the callback function will
599
+ * be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current
600
+ * map
601
+ * @returns a new `LinkedHashMap` object with the values mapped according to the provided callback
602
+ * function.
330
603
  */
331
- map<NV>(callback: (element: [K, V], index: number, map: HashMap<K, V>) => NV): HashMap<K, NV> {
332
- const mappedMap = new HashMap<K, NV>();
604
+ map<NV>(callback: EntryCallback<K, V, NV>, thisArg?: any): LinkedHashMap<K, NV> {
605
+ const mappedMap = new LinkedHashMap<K, NV>();
333
606
  let index = 0;
334
607
  for (const [key, value] of this) {
335
- const newValue = callback([key, value], index, this);
608
+ const newValue = callback.call(thisArg, value, key, index, this);
336
609
  mappedMap.set(key, newValue);
337
610
  index++;
338
611
  }
339
612
  return mappedMap;
340
613
  }
341
614
 
342
- /**
343
- * The `reduce` function iterates over the elements of a HashMap and applies a callback function to
344
- * each element, accumulating a single value.
345
- * @param callback - The callback parameter is a function that takes three arguments: accumulator,
346
- * element, and map. It is called for each element in the HashMap and is used to accumulate a single
347
- * result.
348
- * @param {A} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
349
- * is the value that will be passed as the first argument to the `callback` function when reducing
350
- * the elements of the map.
351
- * @returns The `reduce` function is returning the final value of the accumulator after iterating
352
- * over all the elements in the HashMap and applying the callback function to each element.
353
- */
354
- reduce<A>(callback: (accumulator: A, element: [K, V], index: number, map: HashMap<K, V>) => A, initialValue: A): A {
355
- let accumulator = initialValue;
356
- let index = 0;
357
- for (const entry of this) {
358
- accumulator = callback(accumulator, entry, index, this);
359
- index++;
360
- }
361
- return accumulator;
615
+ print() {
616
+ console.log([...this]);
362
617
  }
363
618
 
364
619
  /**
365
- * Time Complexity: O(n), where n is the number of elements in the HashMap.
620
+ * Time Complexity: O(n), where n is the number of elements in the LinkedHashMap.
366
621
  * Space Complexity: O(1)
367
622
  *
368
623
  * The above function is an iterator that yields key-value pairs from a linked list.
369
624
  */
370
- * [Symbol.iterator]() {
625
+ protected* _getIterator() {
371
626
  let node = this._head;
372
627
  while (node !== this._sentinel) {
373
- yield <[K, V]>[node.key, node.value];
628
+ yield [node.key, node.value] as [K, V];
374
629
  node = node.next;
375
630
  }
376
631
  }
377
632
 
378
- print() {
379
- console.log([...this]);
380
- }
381
-
382
633
  /**
383
634
  * Time Complexity: O(1)
384
635
  * Space Complexity: O(1)
@@ -5,13 +5,15 @@
5
5
  * @license MIT License
6
6
  */
7
7
 
8
- import type { Comparator, DFSOrderPattern } from '../../types';
8
+ import type { Comparator, DFSOrderPattern, ElementCallback } from '../../types';
9
9
  import { HeapOptions } from "../../types";
10
+ import { IterableElementBase } from "../base";
10
11
 
11
- export class Heap<E = any> {
12
+ export class Heap<E = any> extends IterableElementBase<E> {
12
13
  options: HeapOptions<E>;
13
14
 
14
15
  constructor(elements?: Iterable<E>, options?: HeapOptions<E>) {
16
+ super();
15
17
  const defaultComparator = (a: E, b: E) => {
16
18
  if (!(typeof a === 'number' && typeof b === 'number')) {
17
19
  throw new Error('The a, b params of compare function must be number');
@@ -339,56 +341,75 @@ export class Heap<E = any> {
339
341
  for (let i = Math.floor(this.size / 2); i >= 0; i--) this._sinkDown(i, this.elements.length >> 1);
340
342
  }
341
343
 
342
- * [Symbol.iterator]() {
343
- for (const element of this.elements) {
344
- yield element;
345
- }
346
- }
347
-
348
- forEach(callback: (element: E, index: number, heap: this) => void): void {
349
- let index = 0;
350
- for (const el of this) {
351
- callback(el, index, this);
352
- index++;
353
- }
354
- }
344
+ /**
345
+ * Time Complexity: O(n)
346
+ * Space Complexity: O(n)
347
+ */
355
348
 
356
- filter(predicate: (element: E, index: number, heap: Heap<E>) => boolean): Heap<E> {
357
- const filteredHeap: Heap<E> = new Heap<E>([], this.options);
349
+ /**
350
+ * Time Complexity: O(n)
351
+ * Space Complexity: O(n)
352
+ *
353
+ * The `filter` function creates a new Heap object containing elements that pass a given callback
354
+ * function.
355
+ * @param callback - The `callback` parameter is a function that will be called for each element in
356
+ * the heap. It takes three arguments: the current element, the index of the current element, and the
357
+ * heap itself. The callback function should return a boolean value indicating whether the current
358
+ * element should be included in the filtered list
359
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
360
+ * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
361
+ * passed as the `this` value to the `callback` function. If `thisArg` is
362
+ * @returns The `filter` method is returning a new `Heap` object that contains the elements that pass
363
+ * the filter condition specified by the `callback` function.
364
+ */
365
+ filter(callback: ElementCallback<E, boolean>, thisArg?: any): Heap<E> {
366
+ const filteredList = new Heap<E>();
358
367
  let index = 0;
359
- for (const el of this) {
360
- if (predicate(el, index, this)) {
361
- filteredHeap.push(el);
368
+ for (const current of this) {
369
+ if (callback.call(thisArg, current, index, this)) {
370
+ filteredList.push(current);
362
371
  }
363
372
  index++;
364
373
  }
365
- return filteredHeap;
374
+ return filteredList;
366
375
  }
367
376
 
368
- map<T>(callback: (element: E, index: number, heap: Heap<E>) => T, comparator: Comparator<T>): Heap<T> {
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 heap by applying a callback function to each element of the
387
+ * original heap.
388
+ * @param callback - The callback parameter is a function that will be called for each element in the
389
+ * original heap. It takes three arguments: the current element, the index of the current element,
390
+ * and the original heap itself. The callback function should return a value of type T, which will be
391
+ * added to the mapped heap.
392
+ * @param comparator - The `comparator` parameter is a function that is used to compare elements in
393
+ * the heap. It takes two arguments, `a` and `b`, and returns a negative number if `a` is less than
394
+ * `b`, a positive number if `a` is greater than `b`, or
395
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
396
+ * specify the value of `this` within the callback function. It is used when you want to bind a
397
+ * specific object as the context for the callback function. If `thisArg` is not provided,
398
+ * `undefined` is used as
399
+ * @returns a new instance of the Heap class, which is created using the mapped elements from the
400
+ * original Heap.
401
+ */
402
+ map<T>(callback: ElementCallback<E, T>, comparator: Comparator<T>, thisArg?: any): Heap<T> {
369
403
 
370
404
  const mappedHeap: Heap<T> = new Heap<T>([], { comparator: comparator });
371
405
  let index = 0;
372
406
  for (const el of this) {
373
- mappedHeap.add(callback(el, index, this));
407
+ mappedHeap.add(callback.call(thisArg, el, index, this));
374
408
  index++;
375
409
  }
376
410
  return mappedHeap;
377
411
  }
378
412
 
379
- reduce<T>(
380
- callback: (accumulator: T, currentValue: E, currentIndex: number, heap: Heap<E>) => T,
381
- initialValue: T
382
- ): T {
383
- let accumulator: T = initialValue;
384
- let index = 0;
385
- for (const el of this) {
386
- accumulator = callback(accumulator, el, index, this);
387
- index++;
388
- }
389
- return accumulator;
390
- }
391
-
392
413
  /**
393
414
  * Time Complexity: O(log n)
394
415
  * Space Complexity: O(1)
@@ -398,6 +419,12 @@ export class Heap<E = any> {
398
419
  console.log([...this]);
399
420
  }
400
421
 
422
+ protected* _getIterator() {
423
+ for (const element of this.elements) {
424
+ yield element;
425
+ }
426
+ }
427
+
401
428
  /**
402
429
  * Time Complexity: O(n)
403
430
  * Space Complexity: O(1)
@@ -9,3 +9,4 @@ export * from './heap';
9
9
  export * from './priority-queue';
10
10
  export * from './matrix';
11
11
  export * from './trie';
12
+ export * from './base';