min-heap-typed 2.0.4 → 2.1.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 (101) hide show
  1. package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
  2. package/dist/data-structures/base/iterable-element-base.js +149 -107
  3. package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
  4. package/dist/data-structures/base/iterable-entry-base.js +59 -116
  5. package/dist/data-structures/base/linear-base.d.ts +250 -192
  6. package/dist/data-structures/base/linear-base.js +137 -274
  7. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  8. package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
  9. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  10. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  11. package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
  12. package/dist/data-structures/binary-tree/avl-tree.js +208 -195
  13. package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
  14. package/dist/data-structures/binary-tree/binary-tree.js +612 -879
  15. package/dist/data-structures/binary-tree/bst.d.ts +258 -306
  16. package/dist/data-structures/binary-tree/bst.js +505 -481
  17. package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  18. package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
  19. package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
  20. package/dist/data-structures/binary-tree/tree-counter.js +172 -203
  21. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  22. package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
  23. package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
  24. package/dist/data-structures/graph/abstract-graph.js +267 -237
  25. package/dist/data-structures/graph/directed-graph.d.ts +108 -224
  26. package/dist/data-structures/graph/directed-graph.js +146 -233
  27. package/dist/data-structures/graph/map-graph.d.ts +49 -55
  28. package/dist/data-structures/graph/map-graph.js +56 -59
  29. package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
  30. package/dist/data-structures/graph/undirected-graph.js +129 -149
  31. package/dist/data-structures/hash/hash-map.d.ts +164 -338
  32. package/dist/data-structures/hash/hash-map.js +270 -457
  33. package/dist/data-structures/heap/heap.d.ts +214 -289
  34. package/dist/data-structures/heap/heap.js +340 -349
  35. package/dist/data-structures/heap/max-heap.d.ts +11 -47
  36. package/dist/data-structures/heap/max-heap.js +11 -66
  37. package/dist/data-structures/heap/min-heap.d.ts +12 -47
  38. package/dist/data-structures/heap/min-heap.js +11 -66
  39. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  40. package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
  41. package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  42. package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
  43. package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  44. package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
  45. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  46. package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
  47. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  48. package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
  49. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
  50. package/dist/data-structures/priority-queue/priority-queue.js +8 -83
  51. package/dist/data-structures/queue/deque.d.ts +227 -254
  52. package/dist/data-structures/queue/deque.js +309 -348
  53. package/dist/data-structures/queue/queue.d.ts +180 -201
  54. package/dist/data-structures/queue/queue.js +265 -248
  55. package/dist/data-structures/stack/stack.d.ts +124 -102
  56. package/dist/data-structures/stack/stack.js +181 -125
  57. package/dist/data-structures/trie/trie.d.ts +164 -165
  58. package/dist/data-structures/trie/trie.js +189 -172
  59. package/dist/interfaces/binary-tree.d.ts +56 -6
  60. package/dist/interfaces/graph.d.ts +16 -0
  61. package/dist/types/data-structures/base/base.d.ts +1 -1
  62. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
  63. package/dist/types/utils/utils.d.ts +6 -6
  64. package/dist/utils/utils.d.ts +110 -49
  65. package/dist/utils/utils.js +148 -73
  66. package/package.json +2 -2
  67. package/src/data-structures/base/iterable-element-base.ts +238 -115
  68. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  69. package/src/data-structures/base/linear-base.ts +271 -277
  70. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  71. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  72. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  73. package/src/data-structures/binary-tree/binary-tree.ts +681 -905
  74. package/src/data-structures/binary-tree/bst.ts +568 -570
  75. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  76. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  77. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  78. package/src/data-structures/graph/abstract-graph.ts +339 -264
  79. package/src/data-structures/graph/directed-graph.ts +146 -236
  80. package/src/data-structures/graph/map-graph.ts +63 -60
  81. package/src/data-structures/graph/undirected-graph.ts +129 -152
  82. package/src/data-structures/hash/hash-map.ts +274 -496
  83. package/src/data-structures/heap/heap.ts +389 -402
  84. package/src/data-structures/heap/max-heap.ts +12 -76
  85. package/src/data-structures/heap/min-heap.ts +13 -76
  86. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  87. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  88. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  89. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  90. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  91. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  92. package/src/data-structures/queue/deque.ts +381 -357
  93. package/src/data-structures/queue/queue.ts +310 -264
  94. package/src/data-structures/stack/stack.ts +217 -131
  95. package/src/data-structures/trie/trie.ts +240 -175
  96. package/src/interfaces/binary-tree.ts +240 -6
  97. package/src/interfaces/graph.ts +37 -0
  98. package/src/types/data-structures/base/base.ts +5 -5
  99. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  100. package/src/types/utils/utils.ts +9 -5
  101. package/src/utils/utils.ts +152 -86
@@ -5,21 +5,35 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
+
8
9
  import { BST, BSTNode } from './bst';
9
- import type { AVLTreeOptions, BinaryTreeDeleteResult, BSTNOptKeyOrNode, EntryCallback } from '../../types';
10
+ import type {
11
+ AVLTreeOptions,
12
+ BinaryTreeDeleteResult,
13
+ BinaryTreeOptions,
14
+ BSTNOptKeyOrNode,
15
+ EntryCallback,
16
+ IterationType
17
+ } from '../../types';
18
+ import { BSTOptions } from '../../types';
10
19
  import { IBinaryTree } from '../../interfaces';
11
20
 
21
+ /**
22
+ * Represents a Node in an AVL (Adelson-Velsky and Landis) Tree.
23
+ * It extends a BSTNode and ensures the 'height' property is maintained.
24
+ *
25
+ * @template K - The type of the key.
26
+ * @template V - The type of the value.
27
+ */
12
28
  export class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
13
29
  override parent?: AVLTreeNode<K, V> = undefined;
14
30
 
15
31
  /**
16
- * This TypeScript constructor function initializes an instance with a key and an optional value.
17
- * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element
18
- * within a data structure. It serves as a reference or identifier for accessing or manipulating the
19
- * associated value or data.
20
- * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
21
- * have to be provided when creating an instance of the class. If a value is not provided, it will
22
- * default to `undefined`.
32
+ * Creates an instance of AVLTreeNode.
33
+ * @remarks Time O(1), Space O(1)
34
+ *
35
+ * @param key - The key of the node.
36
+ * @param [value] - The value associated with the key.
23
37
  */
24
38
  constructor(key: K, value?: V) {
25
39
  super(key, value);
@@ -27,10 +41,22 @@ export class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
27
41
 
28
42
  override _left?: AVLTreeNode<K, V> | null | undefined = undefined;
29
43
 
44
+ /**
45
+ * Gets the left child of the node.
46
+ * @remarks Time O(1), Space O(1)
47
+ *
48
+ * @returns The left child.
49
+ */
30
50
  override get left(): AVLTreeNode<K, V> | null | undefined {
31
51
  return this._left;
32
52
  }
33
53
 
54
+ /**
55
+ * Sets the left child of the node and updates its parent reference.
56
+ * @remarks Time O(1), Space O(1)
57
+ *
58
+ * @param v - The node to set as the left child.
59
+ */
34
60
  override set left(v: AVLTreeNode<K, V> | null | undefined) {
35
61
  if (v) {
36
62
  v.parent = this;
@@ -40,10 +66,22 @@ export class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
40
66
 
41
67
  override _right?: AVLTreeNode<K, V> | null | undefined = undefined;
42
68
 
69
+ /**
70
+ * Gets the right child of the node.
71
+ * @remarks Time O(1), Space O(1)
72
+ *
73
+ * @returns The right child.
74
+ */
43
75
  override get right(): AVLTreeNode<K, V> | null | undefined {
44
76
  return this._right;
45
77
  }
46
78
 
79
+ /**
80
+ * Sets the right child of the node and updates its parent reference.
81
+ * @remarks Time O(1), Space O(1)
82
+ *
83
+ * @param v - The node to set as the right child.
84
+ */
47
85
  override set right(v: AVLTreeNode<K, V> | null | undefined) {
48
86
  if (v) {
49
87
  v.parent = this;
@@ -53,14 +91,20 @@ export class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
53
91
  }
54
92
 
55
93
  /**
94
+ * Represents a self-balancing AVL (Adelson-Velsky and Landis) Tree.
95
+ * This tree extends BST and performs rotations on add/delete to maintain balance.
96
+ *
97
+ * @template K - The type of the key.
98
+ * @template V - The type of the value.
99
+ * @template R - The type of the raw data object (if using `toEntryFn`).
100
+ *
56
101
  * 1. Height-Balanced: Each node's left and right subtrees differ in height by no more than one.
57
102
  * 2. Automatic Rebalancing: AVL trees rebalance themselves automatically during insertions and deletions.
58
103
  * 3. Rotations for Balancing: Utilizes rotations (single or double) to maintain balance after updates.
59
104
  * 4. Order Preservation: Maintains the binary search tree property where left child values are less than the parent, and right child values are greater.
60
105
  * 5. Efficient Lookups: Offers O(log n) search time, where 'n' is the number of nodes, due to its balanced nature.
61
106
  * 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.
62
- * 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.
63
- * @example
107
+ * 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.@example
64
108
  * // Find elements in a range
65
109
  * // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.
66
110
  * type Datum = { timestamp: Date; temperature: number };
@@ -125,21 +169,13 @@ export class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
125
169
  * // { minute: 15, temperature: 58.6 }
126
170
  * // ]
127
171
  */
128
- export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>
129
- extends BST<K, V, R, MK, MV, MR>
130
- implements IBinaryTree<K, V, R, MK, MV, MR>
131
- {
172
+ export class AVLTree<K = any, V = any, R extends object = object> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
132
173
  /**
133
- * This TypeScript constructor initializes an AVLTree with keys, nodes, entries, or raw data provided
134
- * in an iterable format.
135
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
136
- * iterable that can contain either `
137
- K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R` objects. It is
138
- * used to initialize the AVLTree with key-value pairs or raw data entries. If provided
139
- * @param [options] - The `options` parameter in the constructor is of type `AVLTreeOptions<K, V,
140
- * R>`. It is an optional parameter that allows you to specify additional options for configuring the
141
- * AVL tree. These options could include things like custom comparators, initial capacity, or any
142
- * other configuration settings specific
174
+ * Creates an instance of AVLTree.
175
+ * @remarks Time O(N log N) (from `addMany` with balanced add). Space O(N).
176
+ *
177
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
178
+ * @param [options] - Configuration options for the AVL tree.
143
179
  */
144
180
  constructor(
145
181
  keysNodesEntriesOrRaws: Iterable<
@@ -148,56 +184,28 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
148
184
  options?: AVLTreeOptions<K, V, R>
149
185
  ) {
150
186
  super([], options);
187
+ // Note: super.addMany is called, which in BST defaults to balanced add.
151
188
  if (keysNodesEntriesOrRaws) super.addMany(keysNodesEntriesOrRaws);
152
189
  }
153
190
 
154
191
  /**
155
- * Time Complexity: O(1)
156
- * Space Complexity: O(1)
192
+ * (Protected) Creates a new AVL tree node.
193
+ * @remarks Time O(1), Space O(1)
157
194
  *
158
- * The function creates a new AVL tree node with the given key and value.
159
- * @param {K} key - The key parameter is of type K, which represents the key of the node being
160
- * created.
161
- * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
162
- * value associated with the key in the node being created.
163
- * @returns The method is returning a new instance of the AVLTreeNode class, casted as the generic
164
- * type AVLTreeNode<K, V>.
195
+ * @param key - The key for the new node.
196
+ * @param [value] - The value for the new node.
197
+ * @returns The newly created AVLTreeNode.
165
198
  */
166
- override createNode(key: K, value?: V): AVLTreeNode<K, V> {
199
+ override _createNode(key: K, value?: V): AVLTreeNode<K, V> {
167
200
  return new AVLTreeNode<K, V>(key, this._isMapMode ? undefined : value) as AVLTreeNode<K, V>;
168
201
  }
169
202
 
170
203
  /**
171
- * Time Complexity: O(1)
172
- * Space Complexity: O(1)
173
- *
174
- * The function creates a new AVL tree with the specified options and returns it.
175
- * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be
176
- * passed to the `createTree` function. It is used to customize the behavior of the AVL tree that is
177
- * being created.
178
- * @returns a new AVLTree object.
179
- */
180
- override createTree(options?: AVLTreeOptions<K, V, R>) {
181
- return new AVLTree<K, V, R, MK, MV, MR>([], {
182
- iterationType: this.iterationType,
183
- isMapMode: this._isMapMode,
184
- specifyComparable: this._specifyComparable,
185
- toEntryFn: this._toEntryFn,
186
- isReverse: this._isReverse,
187
- ...options
188
- });
189
- }
190
-
191
- /**
192
- * Time Complexity: O(1)
193
- * Space Complexity: O(1)
204
+ * Checks if the given item is an `AVLTreeNode` instance.
205
+ * @remarks Time O(1), Space O(1)
194
206
  *
195
- * The function checks if the input is an instance of AVLTreeNode.
196
- * @param {K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
197
- * `keyNodeOrEntry` can be of type `R` or `
198
- K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
199
- * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
200
- * an instance of the `AVLTreeNode` class.
207
+ * @param keyNodeOrEntry - The item to check.
208
+ * @returns True if it's an AVLTreeNode, false otherwise.
201
209
  */
202
210
  override isNode(
203
211
  keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -206,17 +214,12 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
206
214
  }
207
215
 
208
216
  /**
209
- * Time Complexity: O(log n)
210
- * Space Complexity: O(log n)
217
+ * Adds a new node to the AVL tree and balances the tree path.
218
+ * @remarks Time O(log N) (O(H) for BST add + O(H) for `_balancePath`). Space O(H) for path/recursion.
211
219
  *
212
- * The function overrides the add method of a class and inserts a key-value pair into a data
213
- * structure, then balances the path.
214
- * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
215
- * `keyNodeOrEntry` can accept values of type `R`, `
216
- K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `
217
- * @param {V} [value] - The `value` parameter is an optional value that you want to associate with
218
- * the key or node being added to the data structure.
219
- * @returns The method is returning a boolean value.
220
+ * @param keyNodeOrEntry - The key, node, or entry to add.
221
+ * @param [value] - The value, if providing just a key.
222
+ * @returns True if the addition was successful, false otherwise.
220
223
  */
221
224
  override add(
222
225
  keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -224,27 +227,23 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
224
227
  ): boolean {
225
228
  if (keyNodeOrEntry === null) return false;
226
229
  const inserted = super.add(keyNodeOrEntry, value);
230
+ // If insertion was successful, balance the path from the new node up to the root.
227
231
  if (inserted) this._balancePath(keyNodeOrEntry);
228
232
  return inserted;
229
233
  }
230
234
 
231
235
  /**
232
- * Time Complexity: O(log n)
233
- * Space Complexity: O(log n)
236
+ * Deletes a node from the AVL tree and re-balances the tree.
237
+ * @remarks Time O(log N) (O(H) for BST delete + O(H) for `_balancePath`). Space O(H) for path/recursion.
234
238
  *
235
- * The function overrides the delete method in a TypeScript class, performs deletion, and then
236
- * balances the tree if necessary.
237
- * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
238
- * parameter in the `override delete` method can be one of the following types:
239
- * @returns The `delete` method is being overridden in this code snippet. It first calls the `delete`
240
- * method from the superclass (presumably a parent class) with the provided `predicate`, which could
241
- * be a key, node, entry, or a custom predicate. The result of this deletion operation is stored in
242
- * `deletedResults`, which is an array of `BinaryTreeDeleteResult` objects.
239
+ * @param keyNodeOrEntry - The node to delete.
240
+ * @returns An array containing deletion results.
243
241
  */
244
242
  override delete(
245
243
  keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
246
244
  ): BinaryTreeDeleteResult<AVLTreeNode<K, V>>[] {
247
245
  const deletedResults = super.delete(keyNodeOrEntry);
246
+ // After deletion, balance the path from the parent of the *physically deleted* node.
248
247
  for (const { needBalanced } of deletedResults) {
249
248
  if (needBalanced) {
250
249
  this._balancePath(needBalanced);
@@ -254,64 +253,115 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
254
253
  }
255
254
 
256
255
  /**
257
- * Time Complexity: O(n)
258
- * Space Complexity: O(n)
256
+ * Rebuilds the tree to be perfectly balanced.
257
+ * @remarks AVL trees are already height-balanced, but this makes them *perfectly* balanced (minimal height and all leaves at N or N-1).
258
+ * Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
259
259
  *
260
- * The `map` function in TypeScript overrides the default map behavior of an AVLTree data structure
261
- * by applying a callback function to each entry and creating a new AVLTree with the results.
262
- * @param callback - A function that will be called for each entry in the AVLTree. It takes four
263
- * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to
264
- * the AVLTree itself.
265
- * @param [options] - The `options` parameter in the `override map` function is of type
266
- * `AVLTreeOptions<MK, MV, MR>`. It is an optional parameter that allows you to specify additional
267
- * options for the AVL tree being created during the mapping process. These options could include
268
- * custom comparators, initial
269
- * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify
270
- * the value of `this` when executing the `callback` function. It allows you to set the context
271
- * (value of `this`) within the callback function. This can be useful when you want to access
272
- * properties or
273
- * @returns The `map` method is returning a new AVLTree instance (`newTree`) with the entries
274
- * modified by the provided callback function.
260
+ * @param [iterationType=this.iterationType] - The traversal method for the initial node export.
261
+ * @returns True if successful, false if the tree was empty.
275
262
  */
276
- override map(
263
+ override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
264
+ const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
265
+ const n = nodes.length;
266
+ if (n === 0) return false;
267
+
268
+ this._clearNodes();
269
+
270
+ // Build balanced tree from sorted array
271
+ const build = (l: number, r: number, parent?: AVLTreeNode<K, V>): AVLTreeNode<K, V> | undefined => {
272
+ if (l > r) return undefined;
273
+ const m = l + ((r - l) >> 1);
274
+ const root = nodes[m]!;
275
+ root.left = build(l, m - 1, root);
276
+ root.right = build(m + 1, r, root);
277
+ root.parent = parent;
278
+
279
+ // Update height during the build
280
+ const lh = root.left ? (root.left as AVLTreeNode<K, V>).height : -1;
281
+ const rh = root.right ? (root.right as AVLTreeNode<K, V>).height : -1;
282
+ root.height = Math.max(lh, rh) + 1;
283
+ return root;
284
+ };
285
+
286
+ const newRoot = build(0, n - 1, undefined);
287
+ this._setRoot(newRoot);
288
+ this._size = n;
289
+ return true;
290
+ }
291
+
292
+ /**
293
+ * Creates a new AVLTree by mapping each [key, value] pair.
294
+ * @remarks Time O(N log N) (O(N) iteration + O(log M) `add` for each item into the new tree). Space O(N) for the new tree.
295
+ *
296
+ * @template MK - New key type.
297
+ * @template MV - New value type.
298
+ * @template MR - New raw type.
299
+ * @param callback - A function to map each [key, value] pair.
300
+ * @param [options] - Options for the new AVLTree.
301
+ * @param [thisArg] - `this` context for the callback.
302
+ * @returns A new, mapped AVLTree.
303
+ */
304
+ override map<MK = K, MV = V, MR extends object = object>(
277
305
  callback: EntryCallback<K, V | undefined, [MK, MV]>,
278
- options?: AVLTreeOptions<MK, MV, MR>,
279
- thisArg?: any
306
+ options?: Partial<BinaryTreeOptions<MK, MV, MR>>,
307
+ thisArg?: unknown
280
308
  ): AVLTree<MK, MV, MR> {
281
- const newTree = new AVLTree<MK, MV, MR>([], options);
309
+ const out = this._createLike<MK, MV, MR>([], options);
310
+
282
311
  let index = 0;
312
+ // Iterates in-order
283
313
  for (const [key, value] of this) {
284
- newTree.add(callback.call(thisArg, key, value, index++, this));
314
+ // `add` on the new tree will be O(log N) and will self-balance.
315
+ out.add(callback.call(thisArg, key, value, index++, this));
285
316
  }
286
- return newTree;
317
+ return out;
287
318
  }
288
319
 
289
320
  /**
290
- * Time Complexity: O(n)
291
- * Space Complexity: O(n)
321
+ * (Protected) Creates a new, empty instance of the same AVLTree constructor.
322
+ * @remarks Time O(1)
292
323
  *
293
- * The function `clone` overrides the default cloning behavior to create a deep copy of a tree
294
- * structure.
295
- * @returns A cloned tree object is being returned.
324
+ * @template TK, TV, TR - Generic types for the new instance.
325
+ * @param [options] - Options for the new tree.
326
+ * @returns A new, empty tree.
296
327
  */
297
- override clone() {
298
- const cloned = this.createTree();
299
- this._clone(cloned);
300
- return cloned;
328
+ protected override _createInstance<TK = K, TV = V, TR extends object = R>(
329
+ options?: Partial<BSTOptions<TK, TV, TR>>
330
+ ): this {
331
+ const Ctor = this.constructor as unknown as new (
332
+ iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
333
+ opts?: BSTOptions<TK, TV, TR>
334
+ ) => this;
335
+ return new Ctor([], { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) }) as unknown as this;
301
336
  }
302
337
 
303
338
  /**
304
- * Time Complexity: O(1)
305
- * Space Complexity: O(1)
339
+ * (Protected) Creates a new instance of the same AVLTree constructor, potentially with different generic types.
340
+ * @remarks Time O(N log N) (from constructor) due to processing the iterable.
306
341
  *
307
- * The `_swapProperties` function swaps the key, value, and height properties between two nodes in a
308
- * binary search tree.
309
- * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} srcNode - The `srcNode` parameter represents either a node
310
- * object (`AVLTreeNode<K, V>`) or a key-value pair (`R`) that is being swapped with another node.
311
- * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} destNode - The `destNode` parameter is either an instance of
312
- * `R` or an instance of `BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>`.
313
- * @returns The method is returning the `destNodeEnsured` object if both `srcNodeEnsured` and
314
- * `destNodeEnsured` are truthy. Otherwise, it returns `undefined`.
342
+ * @template TK, TV, TR - Generic types for the new instance.
343
+ * @param [iter=[]] - An iterable to populate the new tree.
344
+ * @param [options] - Options for the new tree.
345
+ * @returns A new AVLTree.
346
+ */
347
+ protected override _createLike<TK = K, TV = V, TR extends object = R>(
348
+ iter: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR> = [],
349
+ options?: Partial<BSTOptions<TK, TV, TR>>
350
+ ): AVLTree<TK, TV, TR> {
351
+ const Ctor = this.constructor as unknown as new (
352
+ iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
353
+ opts?: BSTOptions<TK, TV, TR>
354
+ ) => AVLTree<TK, TV, TR>;
355
+ return new Ctor(iter, { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) });
356
+ }
357
+
358
+ /**
359
+ * (Protected) Swaps properties of two nodes, including height.
360
+ * @remarks Time O(H) (due to `ensureNode`), but O(1) if nodes are passed directly.
361
+ *
362
+ * @param srcNode - The source node.
363
+ * @param destNode - The destination node.
364
+ * @returns The `destNode` (now holding `srcNode`'s properties).
315
365
  */
316
366
  protected override _swapProperties(
317
367
  srcNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>,
@@ -322,15 +372,17 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
322
372
 
323
373
  if (srcNodeEnsured && destNodeEnsured) {
324
374
  const { key, value, height } = destNodeEnsured;
325
- const tempNode = this.createNode(key, value);
375
+ const tempNode = this._createNode(key, value);
326
376
 
327
377
  if (tempNode) {
328
378
  tempNode.height = height;
329
379
 
380
+ // Copy src to dest
330
381
  destNodeEnsured.key = srcNodeEnsured.key;
331
382
  if (!this._isMapMode) destNodeEnsured.value = srcNodeEnsured.value;
332
383
  destNodeEnsured.height = srcNodeEnsured.height;
333
384
 
385
+ // Copy temp (original dest) to src
334
386
  srcNodeEnsured.key = tempNode.key;
335
387
  if (!this._isMapMode) srcNodeEnsured.value = tempNode.value;
336
388
  srcNodeEnsured.height = tempNode.height;
@@ -342,57 +394,46 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
342
394
  }
343
395
 
344
396
  /**
345
- * Time Complexity: O(1)
346
- * Space Complexity: O(1)
397
+ * (Protected) Calculates the balance factor (height(right) - height(left)).
398
+ * @remarks Time O(1) (assumes heights are stored).
347
399
  *
348
- * The function calculates the balance factor of a node in a binary tree.
349
- * @param {AVLTreeNode<K, V>} node - The parameter "node" is of type "AVLTreeNode<K, V>", which likely represents a node in a
350
- * binary tree data structure.
351
- * @returns the balance factor of a given node. The balance factor is calculated by subtracting the
352
- * height of the left subtree from the height of the right subtree.
400
+ * @param node - The node to check.
401
+ * @returns The balance factor (positive if right-heavy, negative if left-heavy).
353
402
  */
354
403
  protected _balanceFactor(node: AVLTreeNode<K, V>): number {
355
- if (!node.right)
356
- // node has no right subtree
357
- return -node.height;
358
- else if (!node.left)
359
- // node has no left subtree
360
- return +node.height;
361
- else return node.right.height - node.left.height;
404
+ const left = node.left ? (node.left as AVLTreeNode<K, V>).height : -1;
405
+ const right = node.right ? (node.right as AVLTreeNode<K, V>).height : -1;
406
+ return right - left;
362
407
  }
363
408
 
364
409
  /**
365
- * Time Complexity: O(1)
366
- * Space Complexity: O(1)
410
+ * (Protected) Recalculates and updates the height of a node based on its children's heights.
411
+ * @remarks Time O(1) (assumes children's heights are correct).
367
412
  *
368
- * The function updates the height of a node in a binary tree based on the heights of its left and
369
- * right children.
370
- * @param {AVLTreeNode<K, V>} node - The parameter "node" represents a node in a binary tree data structure.
413
+ * @param node - The node to update.
371
414
  */
372
415
  protected _updateHeight(node: AVLTreeNode<K, V>): void {
373
- if (!node.left && !node.right) node.height = 0;
374
- else if (!node.left) {
375
- const rightHeight = node.right ? node.right.height : 0;
376
- node.height = 1 + rightHeight;
377
- } else if (!node.right) node.height = 1 + node.left.height;
378
- else node.height = 1 + Math.max(node.right.height, node.left.height);
416
+ const leftHeight = node.left ? (node.left as AVLTreeNode<K, V>).height : -1;
417
+ const rightHeight = node.right ? (node.right as AVLTreeNode<K, V>).height : -1;
418
+ node.height = 1 + Math.max(leftHeight, rightHeight);
379
419
  }
380
420
 
381
421
  /**
382
- * Time Complexity: O(1)
383
- * Space Complexity: O(1)
422
+ * (Protected) Performs a Left-Left (LL) rotation (a single right rotation).
423
+ * @remarks Time O(1), Space O(1)
384
424
  *
385
- * The `_balanceLL` function performs a left-left rotation to balance a binary search tree.
386
- * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
425
+ * @param A - The unbalanced node (root of the unbalanced subtree).
387
426
  */
388
427
  protected _balanceLL(A: AVLTreeNode<K, V>): void {
389
428
  const parentOfA = A.parent;
390
- const B = A.left;
429
+ const B = A.left; // The left child
391
430
  if (B !== null) A.parent = B;
392
431
  if (B && B.right) {
393
432
  B.right.parent = A;
394
433
  }
395
434
  if (B) B.parent = parentOfA;
435
+
436
+ // Update parent's child pointer
396
437
  if (A === this.root) {
397
438
  if (B) this._setRoot(B);
398
439
  } else {
@@ -403,6 +444,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
403
444
  }
404
445
  }
405
446
 
447
+ // Perform rotation
406
448
  if (B) {
407
449
  A.left = B.right;
408
450
  B.right = A;
@@ -412,18 +454,17 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
412
454
  }
413
455
 
414
456
  /**
415
- * Time Complexity: O(1)
416
- * Space Complexity: O(1)
457
+ * (Protected) Performs a Left-Right (LR) double rotation.
458
+ * @remarks Time O(1), Space O(1)
417
459
  *
418
- * The `_balanceLR` function performs a left-right rotation to balance a binary tree.
419
- * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
460
+ * @param A - The unbalanced node (root of the unbalanced subtree).
420
461
  */
421
462
  protected _balanceLR(A: AVLTreeNode<K, V>): void {
422
463
  const parentOfA = A.parent;
423
464
  const B = A.left;
424
465
  let C = undefined;
425
466
  if (B) {
426
- C = B.right;
467
+ C = B.right; // The "middle" node
427
468
  }
428
469
  if (A && C !== null) A.parent = C;
429
470
  if (B && C !== null) B.parent = C;
@@ -438,6 +479,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
438
479
  C.parent = parentOfA;
439
480
  }
440
481
 
482
+ // Update parent's child pointer
441
483
  if (A === this.root) {
442
484
  if (C) this._setRoot(C);
443
485
  } else {
@@ -450,6 +492,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
450
492
  }
451
493
  }
452
494
 
495
+ // Perform rotation
453
496
  if (C) {
454
497
  A.left = C.right;
455
498
  if (B) B.right = C.left;
@@ -463,15 +506,14 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
463
506
  }
464
507
 
465
508
  /**
466
- * Time Complexity: O(1)
467
- * Space Complexity: O(1)
509
+ * (Protected) Performs a Right-Right (RR) rotation (a single left rotation).
510
+ * @remarks Time O(1), Space O(1)
468
511
  *
469
- * The function `_balanceRR` performs a right-right rotation to balance a binary tree.
470
- * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
512
+ * @param A - The unbalanced node (root of the unbalanced subtree).
471
513
  */
472
514
  protected _balanceRR(A: AVLTreeNode<K, V>): void {
473
515
  const parentOfA = A.parent;
474
- const B = A.right;
516
+ const B = A.right; // The right child
475
517
  if (B !== null) A.parent = B;
476
518
  if (B) {
477
519
  if (B.left) {
@@ -480,6 +522,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
480
522
  B.parent = parentOfA;
481
523
  }
482
524
 
525
+ // Update parent's child pointer
483
526
  if (A === this.root) {
484
527
  if (B) this._setRoot(B);
485
528
  } else {
@@ -492,6 +535,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
492
535
  }
493
536
  }
494
537
 
538
+ // Perform rotation
495
539
  if (B) {
496
540
  A.right = B.left;
497
541
  B.left = A;
@@ -501,18 +545,17 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
501
545
  }
502
546
 
503
547
  /**
504
- * Time Complexity: O(1)
505
- * Space Complexity: O(1)
548
+ * (Protected) Performs a Right-Left (RL) double rotation.
549
+ * @remarks Time O(1), Space O(1)
506
550
  *
507
- * The function `_balanceRL` performs a right-left rotation to balance a binary tree.
508
- * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
551
+ * @param A - The unbalanced node (root of the unbalanced subtree).
509
552
  */
510
553
  protected _balanceRL(A: AVLTreeNode<K, V>): void {
511
554
  const parentOfA = A.parent;
512
555
  const B = A.right;
513
556
  let C = undefined;
514
557
  if (B) {
515
- C = B.left;
558
+ C = B.left; // The "middle" node
516
559
  }
517
560
 
518
561
  if (C !== null) A.parent = C;
@@ -528,6 +571,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
528
571
  C.parent = parentOfA;
529
572
  }
530
573
 
574
+ // Update parent's child pointer
531
575
  if (A === this.root) {
532
576
  if (C) this._setRoot(C);
533
577
  } else {
@@ -540,6 +584,7 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
540
584
  }
541
585
  }
542
586
 
587
+ // Perform rotation
543
588
  if (C) A.right = C.left;
544
589
  if (B && C) B.left = C.right;
545
590
  if (C) C.left = A;
@@ -551,73 +596,61 @@ export class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = obje
551
596
  }
552
597
 
553
598
  /**
554
- * Time Complexity: O(log n)
555
- * Space Complexity: O(1)
599
+ * (Protected) Traverses up the tree from the specified node, updating heights and performing rotations as needed.
600
+ * @remarks Time O(log N) (O(H)), as it traverses the path to root. Space O(H) for the path array.
556
601
  *
557
- * The `_balancePath` function is used to update the heights of nodes and perform rotation operations
558
- * to restore balance in an AVL tree after inserting a node.
559
- * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } node - The `node` parameter can be of type `R` or
560
- * `
561
- K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
602
+ * @param node - The node to start balancing from (e.g., the newly inserted node or parent of the deleted node).
562
603
  */
563
604
  protected _balancePath(node: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): void {
605
+ // Get the path from the node to the root.
564
606
  node = this.ensureNode(node);
565
- const path = this.getPathToRoot(node, node => node, false); // first O(log n) + O(log n)
607
+ const path = this.getPathToRoot(node, node => node, false);
608
+
609
+ // Iterate up the path (from node to root)
566
610
  for (let i = 0; i < path.length; i++) {
567
- // second O(log n)
568
611
  const A = path[i];
569
612
  if (A) {
570
- // Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
571
- this._updateHeight(A); // first O(1)
572
- // Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
573
- // 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:
574
- switch (
575
- this._balanceFactor(A) // second O(1)
576
- ) {
577
- case -2:
613
+ this._updateHeight(A);
614
+
615
+ // Check the balance factor
616
+ switch (this._balanceFactor(A)) {
617
+ case -2: // Left-heavy
578
618
  if (A && A.left) {
579
619
  if (this._balanceFactor(A.left) <= 0) {
580
- // second O(1)
581
- // Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
620
+ // Left-Left case
582
621
  this._balanceLL(A);
583
622
  } else {
584
- // Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
623
+ // Left-Right case
585
624
  this._balanceLR(A);
586
625
  }
587
626
  }
588
627
  break;
589
- case +2:
628
+ case +2: // Right-heavy
590
629
  if (A && A.right) {
591
630
  if (this._balanceFactor(A.right) >= 0) {
592
- // Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
631
+ // Right-Right case
593
632
  this._balanceRR(A);
594
633
  } else {
595
- // Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
634
+ // Right-Left case
596
635
  this._balanceRL(A);
597
636
  }
598
637
  }
599
638
  }
600
- // 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.
601
639
  }
602
640
  }
603
641
  }
604
642
 
605
643
  /**
606
- * Time Complexity: O(1)
607
- * Space Complexity: O(1)
644
+ * (Protected) Replaces a node, ensuring height is copied.
645
+ * @remarks Time O(1)
608
646
  *
609
- * The function replaces an old node with a new node and sets the height of the new node to be the
610
- * same as the old node.
611
- * @param {AVLTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that needs to be replaced in
612
- * the data structure.
613
- * @param {AVLTreeNode<K, V>} newNode - The `newNode` parameter is the new node that will replace the `oldNode` in
614
- * the data structure.
615
- * @returns The method is returning the result of calling the `_replaceNode` method from the
616
- * superclass, with the `oldNode` and `newNode` as arguments.
647
+ * @param oldNode - The node to be replaced.
648
+ * @param newNode - The node to insert.
649
+ * @returns The `newNode`.
617
650
  */
618
651
  protected override _replaceNode(oldNode: AVLTreeNode<K, V>, newNode: AVLTreeNode<K, V>): AVLTreeNode<K, V> {
652
+ // When replacing a node (e.g., on duplicate key), preserve the height.
619
653
  newNode.height = oldNode.height;
620
-
621
654
  return super._replaceNode(oldNode, newNode);
622
655
  }
623
656
  }