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