min-heap-typed 1.50.0 → 1.50.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 (67) hide show
  1. package/dist/data-structures/base/iterable-base.d.ts +114 -9
  2. package/dist/data-structures/base/iterable-base.js +143 -7
  3. package/dist/data-structures/binary-tree/avl-tree.d.ts +43 -46
  4. package/dist/data-structures/binary-tree/avl-tree.js +68 -71
  5. package/dist/data-structures/binary-tree/binary-tree.d.ts +244 -199
  6. package/dist/data-structures/binary-tree/binary-tree.js +484 -376
  7. package/dist/data-structures/binary-tree/bst.d.ts +54 -74
  8. package/dist/data-structures/binary-tree/bst.js +30 -71
  9. package/dist/data-structures/binary-tree/rb-tree.d.ts +78 -60
  10. package/dist/data-structures/binary-tree/rb-tree.js +84 -89
  11. package/dist/data-structures/binary-tree/tree-multimap.d.ts +37 -56
  12. package/dist/data-structures/binary-tree/tree-multimap.js +64 -85
  13. package/dist/data-structures/graph/abstract-graph.d.ts +1 -0
  14. package/dist/data-structures/graph/abstract-graph.js +3 -0
  15. package/dist/data-structures/graph/directed-graph.d.ts +14 -0
  16. package/dist/data-structures/graph/directed-graph.js +26 -0
  17. package/dist/data-structures/graph/map-graph.d.ts +8 -0
  18. package/dist/data-structures/graph/map-graph.js +14 -0
  19. package/dist/data-structures/graph/undirected-graph.d.ts +16 -0
  20. package/dist/data-structures/graph/undirected-graph.js +25 -0
  21. package/dist/data-structures/hash/hash-map.d.ts +121 -15
  22. package/dist/data-structures/hash/hash-map.js +160 -25
  23. package/dist/data-structures/heap/heap.d.ts +66 -6
  24. package/dist/data-structures/heap/heap.js +66 -6
  25. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +67 -50
  26. package/dist/data-structures/linked-list/doubly-linked-list.js +70 -64
  27. package/dist/data-structures/linked-list/singly-linked-list.d.ts +128 -103
  28. package/dist/data-structures/linked-list/singly-linked-list.js +130 -112
  29. package/dist/data-structures/linked-list/skip-linked-list.d.ts +63 -36
  30. package/dist/data-structures/linked-list/skip-linked-list.js +63 -36
  31. package/dist/data-structures/matrix/matrix.d.ts +35 -4
  32. package/dist/data-structures/matrix/matrix.js +50 -11
  33. package/dist/data-structures/queue/deque.d.ts +49 -19
  34. package/dist/data-structures/queue/deque.js +101 -47
  35. package/dist/data-structures/queue/queue.d.ts +39 -5
  36. package/dist/data-structures/queue/queue.js +47 -5
  37. package/dist/data-structures/stack/stack.d.ts +16 -0
  38. package/dist/data-structures/stack/stack.js +22 -0
  39. package/dist/data-structures/trie/trie.d.ts +38 -1
  40. package/dist/data-structures/trie/trie.js +41 -0
  41. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  42. package/dist/types/data-structures/hash/hash-map.d.ts +4 -3
  43. package/dist/types/utils/utils.d.ts +1 -0
  44. package/package.json +2 -2
  45. package/src/data-structures/base/iterable-base.ts +172 -19
  46. package/src/data-structures/binary-tree/avl-tree.ts +97 -97
  47. package/src/data-structures/binary-tree/binary-tree.ts +674 -671
  48. package/src/data-structures/binary-tree/bst.ts +89 -131
  49. package/src/data-structures/binary-tree/rb-tree.ts +127 -155
  50. package/src/data-structures/binary-tree/tree-multimap.ts +96 -112
  51. package/src/data-structures/graph/abstract-graph.ts +4 -0
  52. package/src/data-structures/graph/directed-graph.ts +30 -0
  53. package/src/data-structures/graph/map-graph.ts +15 -0
  54. package/src/data-structures/graph/undirected-graph.ts +28 -0
  55. package/src/data-structures/hash/hash-map.ts +175 -34
  56. package/src/data-structures/heap/heap.ts +66 -6
  57. package/src/data-structures/linked-list/doubly-linked-list.ts +72 -66
  58. package/src/data-structures/linked-list/singly-linked-list.ts +132 -114
  59. package/src/data-structures/linked-list/skip-linked-list.ts +63 -37
  60. package/src/data-structures/matrix/matrix.ts +52 -12
  61. package/src/data-structures/queue/deque.ts +108 -49
  62. package/src/data-structures/queue/queue.ts +51 -5
  63. package/src/data-structures/stack/stack.ts +24 -0
  64. package/src/data-structures/trie/trie.ts +45 -1
  65. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  66. package/src/types/data-structures/hash/hash-map.ts +4 -3
  67. package/src/types/utils/utils.ts +2 -0
@@ -5,3 +5,4 @@ export type Thunk = () => ReturnType<ToThunkFn> & {
5
5
  export type TrlFn = (...args: any[]) => any;
6
6
  export type TrlAsyncFn = (...args: any[]) => any;
7
7
  export type SpecifyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
8
+ export type Any = string | number | boolean | object | null | undefined | symbol;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "min-heap-typed",
3
- "version": "1.50.0",
3
+ "version": "1.50.2",
4
4
  "description": "Min Heap. Javascript & Typescript Data Structure.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -132,6 +132,6 @@
132
132
  "typescript": "^4.9.5"
133
133
  },
134
134
  "dependencies": {
135
- "data-structure-typed": "^1.50.0"
135
+ "data-structure-typed": "^1.50.2"
136
136
  }
137
137
  }
@@ -154,6 +154,105 @@ export abstract class IterableEntryBase<K = any, V = any> {
154
154
  * Time Complexity: O(n)
155
155
  * Space Complexity: O(1)
156
156
  */
157
+
158
+ /**
159
+ * Time Complexity: O(n)
160
+ * Space Complexity: O(1)
161
+ *
162
+ * The `find` function iterates over the entries of a collection and returns the first value for
163
+ * which the callback function returns true.
164
+ * @param callbackfn - The callback function that will be called for each entry in the collection. It
165
+ * takes three arguments: the value of the entry, the key of the entry, and the index of the entry in
166
+ * the collection. It should return a boolean value indicating whether the current entry matches the
167
+ * desired condition.
168
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
169
+ * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
170
+ * be passed as the `this` value to the `callbackfn` function. If `thisArg
171
+ * @returns The method `find` returns the value of the first element in the iterable that satisfies
172
+ * the provided callback function. If no element satisfies the callback function, `undefined` is
173
+ * returned.
174
+ */
175
+ find(callbackfn: EntryCallback<K, V, [K, V]>, thisArg?: any): [K, V] | undefined {
176
+ let index = 0;
177
+ for (const item of this) {
178
+ const [key, value] = item;
179
+ if (callbackfn.call(thisArg, value, key, index++, this)) return item;
180
+ }
181
+ return;
182
+ }
183
+
184
+ /**
185
+ * Time Complexity: O(n)
186
+ * Space Complexity: O(1)
187
+ */
188
+
189
+ /**
190
+ * Time Complexity: O(n)
191
+ * Space Complexity: O(1)
192
+ *
193
+ * The function checks if a given key exists in a collection.
194
+ * @param {K} key - The parameter "key" is of type K, which means it can be any type. It represents
195
+ * the key that we want to check for existence in the data structure.
196
+ * @returns a boolean value. It returns true if the key is found in the collection, and false
197
+ * otherwise.
198
+ */
199
+ has(key: K): boolean {
200
+ for (const item of this) {
201
+ const [itemKey] = item;
202
+ if (itemKey === key) return true;
203
+ }
204
+ return false;
205
+ }
206
+
207
+ /**
208
+ * Time Complexity: O(n)
209
+ * Space Complexity: O(1)
210
+ */
211
+
212
+ /**
213
+ * Time Complexity: O(n)
214
+ * Space Complexity: O(1)
215
+ *
216
+ * The function checks if a given value exists in a collection.
217
+ * @param {V} value - The parameter "value" is the value that we want to check if it exists in the
218
+ * collection.
219
+ * @returns a boolean value, either true or false.
220
+ */
221
+ hasValue(value: V): boolean {
222
+ for (const [, elementValue] of this) {
223
+ if (elementValue === value) return true;
224
+ }
225
+ return false;
226
+ }
227
+
228
+ /**
229
+ * Time Complexity: O(n)
230
+ * Space Complexity: O(1)
231
+ */
232
+
233
+ /**
234
+ * Time Complexity: O(n)
235
+ * Space Complexity: O(1)
236
+ *
237
+ * The `get` function retrieves the value associated with a given key from a collection.
238
+ * @param {K} key - K (the type of the key) - This parameter represents the key that is being
239
+ * searched for in the collection.
240
+ * @returns The `get` method returns the value associated with the specified key if it exists in the
241
+ * collection, otherwise it returns `undefined`.
242
+ */
243
+ get(key: K): V | undefined {
244
+ for (const item of this) {
245
+ const [itemKey, value] = item;
246
+ if (itemKey === key) return value;
247
+ }
248
+ return;
249
+ }
250
+
251
+ /**
252
+ * Time Complexity: O(n)
253
+ * Space Complexity: O(1)
254
+ */
255
+
157
256
  /**
158
257
  * Time Complexity: O(n)
159
258
  * Space Complexity: O(1)
@@ -180,13 +279,6 @@ export abstract class IterableEntryBase<K = any, V = any> {
180
279
  return accumulator;
181
280
  }
182
281
 
183
- hasValue(value: V): boolean {
184
- for (const [, elementValue] of this) {
185
- if (elementValue === value) return true;
186
- }
187
- return false;
188
- }
189
-
190
282
  /**
191
283
  * Time Complexity: O(n)
192
284
  * Space Complexity: O(n)
@@ -195,10 +287,14 @@ export abstract class IterableEntryBase<K = any, V = any> {
195
287
  console.log([...this]);
196
288
  }
197
289
 
290
+ abstract isEmpty(): boolean;
291
+
292
+ abstract clone(): any;
293
+
198
294
  protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
199
295
  }
200
296
 
201
- export abstract class IterableElementBase<V> {
297
+ export abstract class IterableElementBase<E = any, C = any> {
202
298
  /**
203
299
  * Time Complexity: O(n)
204
300
  * Space Complexity: O(1)
@@ -212,7 +308,7 @@ export abstract class IterableElementBase<V> {
212
308
  * allows the function to accept any number of arguments as an array. In this case, the `args`
213
309
  * parameter is used to pass any number of arguments to the `_getIterator` method.
214
310
  */
215
- * [Symbol.iterator](...args: any[]): IterableIterator<V> {
311
+ * [Symbol.iterator](...args: any[]): IterableIterator<E> {
216
312
  yield* this._getIterator(...args);
217
313
  }
218
314
 
@@ -226,7 +322,7 @@ export abstract class IterableElementBase<V> {
226
322
  *
227
323
  * The function returns an iterator that yields all the values in the object.
228
324
  */
229
- * values(): IterableIterator<V> {
325
+ * values(): IterableIterator<E> {
230
326
  for (const item of this) {
231
327
  yield item;
232
328
  }
@@ -250,10 +346,10 @@ export abstract class IterableElementBase<V> {
250
346
  * @returns The `every` method is returning a boolean value. It returns `true` if every element in
251
347
  * the array satisfies the provided predicate function, and `false` otherwise.
252
348
  */
253
- every(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
349
+ every(predicate: ElementCallback<E, boolean>, thisArg?: any): boolean {
254
350
  let index = 0;
255
351
  for (const item of this) {
256
- if (!predicate.call(thisArg, item as V, index++, this)) {
352
+ if (!predicate.call(thisArg, item, index++, this)) {
257
353
  return false;
258
354
  }
259
355
  }
@@ -278,10 +374,10 @@ export abstract class IterableElementBase<V> {
278
374
  * @returns a boolean value. It returns true if the predicate function returns true for any element
279
375
  * in the collection, and false otherwise.
280
376
  */
281
- some(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
377
+ some(predicate: ElementCallback<E, boolean>, thisArg?: any): boolean {
282
378
  let index = 0;
283
379
  for (const item of this) {
284
- if (predicate.call(thisArg, item as V, index++, this)) {
380
+ if (predicate.call(thisArg, item, index++, this)) {
285
381
  return true;
286
382
  }
287
383
  }
@@ -292,6 +388,7 @@ export abstract class IterableElementBase<V> {
292
388
  * Time Complexity: O(n)
293
389
  * Space Complexity: O(1)
294
390
  */
391
+
295
392
  /**
296
393
  * Time Complexity: O(n)
297
394
  * Space Complexity: O(1)
@@ -305,13 +402,65 @@ export abstract class IterableElementBase<V> {
305
402
  * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
306
403
  * be passed as the `this` value to the `callbackfn` function. If `thisArg
307
404
  */
308
- forEach(callbackfn: ElementCallback<V, void>, thisArg?: any): void {
405
+ forEach(callbackfn: ElementCallback<E, void>, thisArg?: any): void {
309
406
  let index = 0;
310
407
  for (const item of this) {
311
- callbackfn.call(thisArg, item as V, index++, this);
408
+ callbackfn.call(thisArg, item, index++, this);
312
409
  }
313
410
  }
314
411
 
412
+ /**
413
+ * Time Complexity: O(n)
414
+ * Space Complexity: O(1)
415
+ */
416
+
417
+ /**
418
+ * Time Complexity: O(n)
419
+ * Space Complexity: O(1)
420
+ *
421
+ * The `find` function iterates over the elements of an array-like object and returns the first
422
+ * element that satisfies the provided callback function.
423
+ * @param callbackfn - The callbackfn parameter is a function that will be called for each element in
424
+ * the array. It takes three arguments: the current element being processed, the index of the current
425
+ * element, and the array itself. The function should return a boolean value indicating whether the
426
+ * current element matches the desired condition.
427
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
428
+ * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
429
+ * be passed as the `this` value to the `callbackfn` function. If `thisArg
430
+ * @returns The `find` method returns the first element in the array that satisfies the provided
431
+ * callback function. If no element satisfies the callback function, `undefined` is returned.
432
+ */
433
+ find(callbackfn: ElementCallback<E, boolean>, thisArg?: any): E | undefined {
434
+ let index = 0;
435
+ for (const item of this) {
436
+ if (callbackfn.call(thisArg, item, index++, this)) return item;
437
+ }
438
+
439
+ return;
440
+ }
441
+
442
+ /**
443
+ * Time Complexity: O(n)
444
+ * Space Complexity: O(1)
445
+ */
446
+
447
+ /**
448
+ * Time Complexity: O(n)
449
+ * Space Complexity: O(1)
450
+ *
451
+ * The function checks if a given element exists in a collection.
452
+ * @param {E} element - The parameter "element" is of type E, which means it can be any type. It
453
+ * represents the element that we want to check for existence in the collection.
454
+ * @returns a boolean value. It returns true if the element is found in the collection, and false
455
+ * otherwise.
456
+ */
457
+ has(element: E): boolean {
458
+ for (const ele of this) {
459
+ if (ele === element) return true;
460
+ }
461
+ return false;
462
+ }
463
+
315
464
  /**
316
465
  * Time Complexity: O(n)
317
466
  * Space Complexity: O(1)
@@ -329,11 +478,11 @@ export abstract class IterableElementBase<V> {
329
478
  * @returns The `reduce` method is returning the final value of the accumulator after iterating over
330
479
  * all the elements in the array and applying the callback function to each element.
331
480
  */
332
- reduce<U>(callbackfn: ReduceElementCallback<V, U>, initialValue: U): U {
481
+ reduce<U>(callbackfn: ReduceElementCallback<E, U>, initialValue: U): U {
333
482
  let accumulator = initialValue;
334
483
  let index = 0;
335
484
  for (const item of this) {
336
- accumulator = callbackfn(accumulator, item as V, index++, this);
485
+ accumulator = callbackfn(accumulator, item as E, index++, this);
337
486
  }
338
487
  return accumulator;
339
488
  }
@@ -346,5 +495,9 @@ export abstract class IterableElementBase<V> {
346
495
  console.log([...this]);
347
496
  }
348
497
 
349
- protected abstract _getIterator(...args: any[]): IterableIterator<V>;
498
+ abstract isEmpty(): boolean;
499
+
500
+ abstract clone(): C;
501
+
502
+ protected abstract _getIterator(...args: any[]): IterableIterator<E>;
350
503
  }
@@ -17,11 +17,11 @@ import type {
17
17
  } from '../../types';
18
18
  import { IBinaryTree } from '../../interfaces';
19
19
 
20
- export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeNodeNested<K, V>> extends BSTNode<
21
- K,
22
- V,
23
- N
24
- > {
20
+ export class AVLTreeNode<
21
+ K = any,
22
+ V = any,
23
+ NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNodeNested<K, V>
24
+ > extends BSTNode<K, V, NODE> {
25
25
  height: number;
26
26
 
27
27
  constructor(key: K, value?: V) {
@@ -42,21 +42,21 @@ export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLT
42
42
  export class AVLTree<
43
43
  K = any,
44
44
  V = any,
45
- N extends AVLTreeNode<K, V, N> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
46
- TREE extends AVLTree<K, V, N, TREE> = AVLTree<K, V, N, AVLTreeNested<K, V, N>>
45
+ NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
46
+ TREE extends AVLTree<K, V, NODE, TREE> = AVLTree<K, V, NODE, AVLTreeNested<K, V, NODE>>
47
47
  >
48
- extends BST<K, V, N, TREE>
49
- implements IBinaryTree<K, V, N, TREE> {
48
+ extends BST<K, V, NODE, TREE>
49
+ implements IBinaryTree<K, V, NODE, TREE> {
50
50
  /**
51
51
  * The constructor function initializes an AVLTree object with optional keysOrNodesOrEntries and options.
52
- * @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry<K, V, N>`
52
+ * @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry<K, V, NODE>`
53
53
  * objects. It represents a collection of nodes that will be added to the AVL tree during
54
54
  * initialization.
55
55
  * @param [options] - The `options` parameter is an optional object that allows you to customize the
56
56
  * behavior of the AVL tree. It is of type `Partial<AVLTreeOptions>`, which means that you can
57
57
  * provide only a subset of the properties defined in the `AVLTreeOptions` interface.
58
58
  */
59
- constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, N>> = [], options?: AVLTreeOptions<K>) {
59
+ constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: AVLTreeOptions<K>) {
60
60
  super([], options);
61
61
  if (keysOrNodesOrEntries) super.addMany(keysOrNodesOrEntries);
62
62
  }
@@ -67,11 +67,11 @@ export class AVLTree<
67
67
  * the new node. It is used to determine the position of the node in the binary search tree.
68
68
  * @param [value] - The parameter `value` is an optional value that can be assigned to the node. It is of
69
69
  * type `V`, which means it can be any value that is assignable to the `value` property of the
70
- * node type `N`.
70
+ * node type `NODE`.
71
71
  * @returns a new AVLTreeNode object with the specified key and value.
72
72
  */
73
- override createNode(key: K, value?: V): N {
74
- return new AVLTreeNode<K, V, N>(key, value) as N;
73
+ override createNode(key: K, value?: V): NODE {
74
+ return new AVLTreeNode<K, V, NODE>(key, value) as NODE;
75
75
  }
76
76
 
77
77
  /**
@@ -82,7 +82,7 @@ export class AVLTree<
82
82
  * @returns a new AVLTree object.
83
83
  */
84
84
  override createTree(options?: AVLTreeOptions<K>): TREE {
85
- return new AVLTree<K, V, N, TREE>([], {
85
+ return new AVLTree<K, V, NODE, TREE>([], {
86
86
  iterationType: this.iterationType,
87
87
  variant: this.variant,
88
88
  ...options
@@ -91,10 +91,10 @@ export class AVLTree<
91
91
 
92
92
  /**
93
93
  * The function checks if an keyOrNodeOrEntry is an instance of AVLTreeNode.
94
- * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V, N>`.
94
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V, NODE>`.
95
95
  * @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the AVLTreeNode class.
96
96
  */
97
- override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, N>): keyOrNodeOrEntry is N {
97
+ override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is NODE {
98
98
  return keyOrNodeOrEntry instanceof AVLTreeNode;
99
99
  }
100
100
 
@@ -116,7 +116,7 @@ export class AVLTree<
116
116
  * being added to the binary tree.
117
117
  * @returns The method is returning either the inserted node or undefined.
118
118
  */
119
- override add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, N>, value?: V): boolean {
119
+ override add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
120
120
  if (keyOrNodeOrEntry === null) return false;
121
121
  const inserted = super.add(keyOrNodeOrEntry, value);
122
122
  if (inserted) this._balancePath(keyOrNodeOrEntry);
@@ -140,13 +140,13 @@ export class AVLTree<
140
140
  * @param {C} callback - The `callback` parameter is a function that will be called for each node
141
141
  * that is deleted from the binary tree. It is an optional parameter and if not provided, it will
142
142
  * default to the `_defaultOneParamCallback` function. The `callback` function should have a single
143
- * parameter of type `N
144
- * @returns The method is returning an array of `BinaryTreeDeleteResult<N>`.
143
+ * parameter of type `NODE
144
+ * @returns The method is returning an array of `BinaryTreeDeleteResult<NODE>`.
145
145
  */
146
- override delete<C extends BTNCallback<N>>(
146
+ override delete<C extends BTNCallback<NODE>>(
147
147
  identifier: ReturnType<C>,
148
148
  callback: C = this._defaultOneParamCallback as C
149
- ): BinaryTreeDeleteResult<N>[] {
149
+ ): BinaryTreeDeleteResult<NODE>[] {
150
150
  if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C;
151
151
  const deletedResults = super.delete(identifier, callback);
152
152
  for (const { needBalanced } of deletedResults) {
@@ -160,14 +160,17 @@ export class AVLTree<
160
160
  /**
161
161
  * The `_swapProperties` function swaps the key, value, and height properties between two nodes in a binary
162
162
  * tree.
163
- * @param {K | N | undefined} srcNode - The `srcNode` parameter represents the source node that
164
- * needs to be swapped with the destination node. It can be of type `K`, `N`, or `undefined`.
165
- * @param {K | N | undefined} destNode - The `destNode` parameter represents the destination
163
+ * @param {K | NODE | undefined} srcNode - The `srcNode` parameter represents the source node that
164
+ * needs to be swapped with the destination node. It can be of type `K`, `NODE`, or `undefined`.
165
+ * @param {K | NODE | undefined} destNode - The `destNode` parameter represents the destination
166
166
  * node where the values from the source node will be swapped to.
167
167
  * @returns either the `destNode` object if both `srcNode` and `destNode` are defined, or `undefined`
168
168
  * if either `srcNode` or `destNode` is undefined.
169
169
  */
170
- protected override _swapProperties(srcNode: BSTNKeyOrNode<K, N>, destNode: BSTNKeyOrNode<K, N>): N | undefined {
170
+ protected override _swapProperties(
171
+ srcNode: BSTNKeyOrNode<K, NODE>,
172
+ destNode: BSTNKeyOrNode<K, NODE>
173
+ ): NODE | undefined {
171
174
  srcNode = this.ensureNode(srcNode);
172
175
  destNode = this.ensureNode(destNode);
173
176
 
@@ -195,7 +198,6 @@ export class AVLTree<
195
198
  /**
196
199
  * Time Complexity: O(1)
197
200
  * Space Complexity: O(1)
198
- * constant time, as it performs a fixed number of operations. constant space, as it only uses a constant amount of memory.
199
201
  */
200
202
 
201
203
  /**
@@ -203,11 +205,11 @@ export class AVLTree<
203
205
  * Space Complexity: O(1)
204
206
  *
205
207
  * The function calculates the balance factor of a node in a binary tree.
206
- * @param {N} node - The parameter "node" represents a node in a binary tree data structure.
208
+ * @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
207
209
  * @returns the balance factor of a given node. The balance factor is calculated by subtracting the
208
210
  * height of the left subtree from the height of the right subtree.
209
211
  */
210
- protected _balanceFactor(node: N): number {
212
+ protected _balanceFactor(node: NODE): number {
211
213
  if (!node.right)
212
214
  // node has no right subtree
213
215
  return -node.height;
@@ -220,7 +222,6 @@ export class AVLTree<
220
222
  /**
221
223
  * Time Complexity: O(1)
222
224
  * Space Complexity: O(1)
223
- * constant time, as it performs a fixed number of operations. constant space, as it only uses a constant amount of memory.
224
225
  */
225
226
 
226
227
  /**
@@ -229,9 +230,9 @@ export class AVLTree<
229
230
  *
230
231
  * The function updates the height of a node in a binary tree based on the heights of its left and
231
232
  * right children.
232
- * @param {N} node - The parameter "node" represents a node in a binary tree data structure.
233
+ * @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
233
234
  */
234
- protected _updateHeight(node: N): void {
235
+ protected _updateHeight(node: NODE): void {
235
236
  if (!node.left && !node.right) node.height = 0;
236
237
  else if (!node.left) {
237
238
  const rightHeight = node.right ? node.right.height : 0;
@@ -240,65 +241,9 @@ export class AVLTree<
240
241
  else node.height = 1 + Math.max(node.right.height, node.left.height);
241
242
  }
242
243
 
243
- /**
244
- * Time Complexity: O(log n)
245
- * Space Complexity: O(1)
246
- * logarithmic time, where "n" is the number of nodes in the tree. The method traverses the path from the inserted node to the root. constant space, as it doesn't use additional data structures that scale with input size.
247
- */
248
-
249
- /**
250
- * Time Complexity: O(log n)
251
- * Space Complexity: O(1)
252
- *
253
- * The `_balancePath` function is used to update the heights of nodes and perform rotation operations
254
- * to restore balance in an AVL tree after inserting a node.
255
- * @param {N} node - The `node` parameter in the `_balancePath` function represents the node in the
256
- * AVL tree that needs to be balanced.
257
- */
258
- protected _balancePath(node: KeyOrNodeOrEntry<K, V, N>): void {
259
- node = this.ensureNode(node);
260
- const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
261
- for (let i = 0; i < path.length; i++) {
262
- // second O(log n)
263
- const A = path[i];
264
- // Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
265
- this._updateHeight(A); // first O(1)
266
- // Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
267
- // Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
268
- switch (
269
- this._balanceFactor(A) // second O(1)
270
- ) {
271
- case -2:
272
- if (A && A.left) {
273
- if (this._balanceFactor(A.left) <= 0) {
274
- // second O(1)
275
- // Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
276
- this._balanceLL(A);
277
- } else {
278
- // Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
279
- this._balanceLR(A);
280
- }
281
- }
282
- break;
283
- case +2:
284
- if (A && A.right) {
285
- if (this._balanceFactor(A.right) >= 0) {
286
- // Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
287
- this._balanceRR(A);
288
- } else {
289
- // Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
290
- this._balanceRL(A);
291
- }
292
- }
293
- }
294
- // TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
295
- }
296
- }
297
-
298
244
  /**
299
245
  * Time Complexity: O(1)
300
246
  * Space Complexity: O(1)
301
- * constant time, as these methods perform a fixed number of operations. constant space, as they only use a constant amount of memory.
302
247
  */
303
248
 
304
249
  /**
@@ -306,9 +251,9 @@ export class AVLTree<
306
251
  * Space Complexity: O(1)
307
252
  *
308
253
  * The function `_balanceLL` performs a left-left rotation to balance a binary tree.
309
- * @param {N} A - A is a node in a binary tree.
254
+ * @param {NODE} A - A is a node in a binary tree.
310
255
  */
311
- protected _balanceLL(A: N): void {
256
+ protected _balanceLL(A: NODE): void {
312
257
  const parentOfA = A.parent;
313
258
  const B = A.left;
314
259
  A.parent = B;
@@ -344,9 +289,9 @@ export class AVLTree<
344
289
  * Space Complexity: O(1)
345
290
  *
346
291
  * The `_balanceLR` function performs a left-right rotation to balance a binary tree.
347
- * @param {N} A - A is a node in a binary tree.
292
+ * @param {NODE} A - A is a node in a binary tree.
348
293
  */
349
- protected _balanceLR(A: N): void {
294
+ protected _balanceLR(A: NODE): void {
350
295
  const parentOfA = A.parent;
351
296
  const B = A.left;
352
297
  let C = undefined;
@@ -400,9 +345,9 @@ export class AVLTree<
400
345
  * Space Complexity: O(1)
401
346
  *
402
347
  * The function `_balanceRR` performs a right-right rotation to balance a binary tree.
403
- * @param {N} A - A is a node in a binary tree.
348
+ * @param {NODE} A - A is a node in a binary tree.
404
349
  */
405
- protected _balanceRR(A: N): void {
350
+ protected _balanceRR(A: NODE): void {
406
351
  const parentOfA = A.parent;
407
352
  const B = A.right;
408
353
  A.parent = B;
@@ -443,9 +388,9 @@ export class AVLTree<
443
388
  * Space Complexity: O(1)
444
389
  *
445
390
  * The function `_balanceRL` performs a right-left rotation to balance a binary tree.
446
- * @param {N} A - A is a node in a binary tree.
391
+ * @param {NODE} A - A is a node in a binary tree.
447
392
  */
448
- protected _balanceRL(A: N): void {
393
+ protected _balanceRL(A: NODE): void {
449
394
  const parentOfA = A.parent;
450
395
  const B = A.right;
451
396
  let C = undefined;
@@ -488,7 +433,62 @@ export class AVLTree<
488
433
  C && this._updateHeight(C);
489
434
  }
490
435
 
491
- protected _replaceNode(oldNode: N, newNode: N): N {
436
+ /**
437
+ * Time Complexity: O(log n)
438
+ * Space Complexity: O(1)
439
+ * logarithmic time, where "n" is the number of nodes in the tree. The method traverses the path from the inserted node to the root. constant space, as it doesn't use additional data structures that scale with input size.
440
+ */
441
+
442
+ /**
443
+ * Time Complexity: O(log n)
444
+ * Space Complexity: O(1)
445
+ *
446
+ * The `_balancePath` function is used to update the heights of nodes and perform rotation operations
447
+ * to restore balance in an AVL tree after inserting a node.
448
+ * @param {NODE} node - The `node` parameter in the `_balancePath` function represents the node in the
449
+ * AVL tree that needs to be balanced.
450
+ */
451
+ protected _balancePath(node: KeyOrNodeOrEntry<K, V, NODE>): void {
452
+ node = this.ensureNode(node);
453
+ const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
454
+ for (let i = 0; i < path.length; i++) {
455
+ // second O(log n)
456
+ const A = path[i];
457
+ // Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
458
+ this._updateHeight(A); // first O(1)
459
+ // Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
460
+ // Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
461
+ switch (
462
+ this._balanceFactor(A) // second O(1)
463
+ ) {
464
+ case -2:
465
+ if (A && A.left) {
466
+ if (this._balanceFactor(A.left) <= 0) {
467
+ // second O(1)
468
+ // Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
469
+ this._balanceLL(A);
470
+ } else {
471
+ // Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
472
+ this._balanceLR(A);
473
+ }
474
+ }
475
+ break;
476
+ case +2:
477
+ if (A && A.right) {
478
+ if (this._balanceFactor(A.right) >= 0) {
479
+ // Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
480
+ this._balanceRR(A);
481
+ } else {
482
+ // Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
483
+ this._balanceRL(A);
484
+ }
485
+ }
486
+ }
487
+ // TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
488
+ }
489
+ }
490
+
491
+ protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
492
492
  newNode.height = oldNode.height;
493
493
 
494
494
  return super._replaceNode(oldNode, newNode);