graph-typed 2.0.5 → 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 +598 -869
  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 +1 -0
  64. package/dist/utils/utils.d.ts +1 -1
  65. package/dist/utils/utils.js +2 -1
  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 +664 -893
  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 +2 -0
  101. package/src/utils/utils.ts +9 -14
@@ -1,19 +1,30 @@
1
1
  "use strict";
2
+ /**
3
+ * data-structure-typed
4
+ *
5
+ * @author Pablo Zeng
6
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
7
+ * @license MIT License
8
+ */
2
9
  Object.defineProperty(exports, "__esModule", { value: true });
3
10
  exports.BST = exports.BSTNode = void 0;
4
11
  const binary_tree_1 = require("./binary-tree");
5
12
  const queue_1 = require("../queue");
6
13
  const utils_1 = require("../../utils");
7
14
  const common_1 = require("../../common");
15
+ /**
16
+ * Represents a Node in a Binary Search Tree.
17
+ *
18
+ * @template K - The type of the key.
19
+ * @template V - The type of the value.
20
+ */
8
21
  class BSTNode extends binary_tree_1.BinaryTreeNode {
9
22
  /**
10
- * This TypeScript constructor function initializes an instance with a key and an optional value.
11
- * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element
12
- * within a data structure. It serves as a reference or identifier for accessing or manipulating the
13
- * associated value.
14
- * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
15
- * have to be provided when creating an instance of the class. If a value is not provided, it will
16
- * default to `undefined`.
23
+ * Creates an instance of BSTNode.
24
+ * @remarks Time O(1), Space O(1)
25
+ *
26
+ * @param key - The key of the node.
27
+ * @param [value] - The value associated with the key.
17
28
  */
18
29
  constructor(key, value) {
19
30
  super(key, value);
@@ -21,27 +32,55 @@ class BSTNode extends binary_tree_1.BinaryTreeNode {
21
32
  this._left = undefined;
22
33
  this._right = undefined;
23
34
  }
35
+ /**
36
+ * Gets the left child of the node.
37
+ * @remarks Time O(1), Space O(1)
38
+ *
39
+ * @returns The left child.
40
+ */
24
41
  get left() {
25
42
  return this._left;
26
43
  }
44
+ /**
45
+ * Sets the left child of the node and updates its parent reference.
46
+ * @remarks Time O(1), Space O(1)
47
+ *
48
+ * @param v - The node to set as the left child.
49
+ */
27
50
  set left(v) {
28
- if (v) {
51
+ if (v)
29
52
  v.parent = this;
30
- }
31
53
  this._left = v;
32
54
  }
55
+ /**
56
+ * Gets the right child of the node.
57
+ * @remarks Time O(1), Space O(1)
58
+ *
59
+ * @returns The right child.
60
+ */
33
61
  get right() {
34
62
  return this._right;
35
63
  }
64
+ /**
65
+ * Sets the right child of the node and updates its parent reference.
66
+ * @remarks Time O(1), Space O(1)
67
+ *
68
+ * @param v - The node to set as the right child.
69
+ */
36
70
  set right(v) {
37
- if (v) {
71
+ if (v)
38
72
  v.parent = this;
39
- }
40
73
  this._right = v;
41
74
  }
42
75
  }
43
76
  exports.BSTNode = BSTNode;
44
77
  /**
78
+ * Represents a Binary Search Tree (BST).
79
+ * Keys are ordered, allowing for faster search operations compared to a standard Binary Tree.
80
+ * @template K - The type of the key.
81
+ * @template V - The type of the value.
82
+ * @template R - The type of the raw data object (if using `toEntryFn`).
83
+ *
45
84
  * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
46
85
  * 2. Unique Keys: No duplicate keys in a standard BST.
47
86
  * 3. Efficient Search: Enables quick search, minimum, and maximum operations.
@@ -108,18 +147,20 @@ exports.BSTNode = BSTNode;
108
147
  */
109
148
  class BST extends binary_tree_1.BinaryTree {
110
149
  /**
111
- * This TypeScript constructor initializes a binary search tree with optional options and adds
112
- * elements if provided.
113
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
114
- * iterable that can contain elements of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It is used to
115
- * initialize the binary search tree with keys, nodes, entries, or raw data.
116
- * @param [options] - The `options` parameter is an optional object that can contain the following
117
- * properties:
150
+ * Creates an instance of BST.
151
+ * @remarks Time O(N log N) or O(N^2) depending on `isBalanceAdd` in `addMany` and input order. Space O(N).
152
+ *
153
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
154
+ * @param [options] - Configuration options for the BST, including comparator.
118
155
  */
119
156
  constructor(keysNodesEntriesOrRaws = [], options) {
120
157
  super([], options);
121
158
  this._root = undefined;
122
159
  this._isReverse = false;
160
+ /**
161
+ * The default comparator function.
162
+ * @remarks Time O(1) (or O(C) if `specifyComparable` is used, C is complexity of that function).
163
+ */
123
164
  this._comparator = (a, b) => {
124
165
  if ((0, utils_1.isComparable)(a) && (0, utils_1.isComparable)(b)) {
125
166
  if (a > b)
@@ -129,14 +170,16 @@ class BST extends binary_tree_1.BinaryTree {
129
170
  return 0;
130
171
  }
131
172
  if (this._specifyComparable) {
132
- if (this._specifyComparable(a) > this._specifyComparable(b))
173
+ const va = this._specifyComparable(a);
174
+ const vb = this._specifyComparable(b);
175
+ if (va > vb)
133
176
  return 1;
134
- if (this._specifyComparable(a) < this._specifyComparable(b))
177
+ if (va < vb)
135
178
  return -1;
136
179
  return 0;
137
180
  }
138
181
  if (typeof a === 'object' || typeof b === 'object') {
139
- throw TypeError(`When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`);
182
+ throw TypeError(`When comparing object types, a custom specifyComparable must be defined in the constructor's options.`);
140
183
  }
141
184
  return 0;
142
185
  };
@@ -150,101 +193,240 @@ class BST extends binary_tree_1.BinaryTree {
150
193
  if (keysNodesEntriesOrRaws)
151
194
  this.addMany(keysNodesEntriesOrRaws);
152
195
  }
196
+ /**
197
+ * Gets the root node of the tree.
198
+ * @remarks Time O(1)
199
+ *
200
+ * @returns The root node.
201
+ */
153
202
  get root() {
154
203
  return this._root;
155
204
  }
205
+ /**
206
+ * Gets whether the tree's comparison logic is reversed.
207
+ * @remarks Time O(1)
208
+ *
209
+ * @returns True if the tree is reversed (e.g., a max-heap logic).
210
+ */
156
211
  get isReverse() {
157
212
  return this._isReverse;
158
213
  }
214
+ /**
215
+ * Gets the comparator function used by the tree.
216
+ * @remarks Time O(1)
217
+ *
218
+ * @returns The comparator function.
219
+ */
159
220
  get comparator() {
160
221
  return this._comparator;
161
222
  }
162
- get specifyComparable() {
163
- return this._specifyComparable;
164
- }
165
223
  /**
166
- * Time Complexity: O(1)
167
- * Space Complexity: O(1)
224
+ * Gets the function used to extract a comparable value from a complex key.
225
+ * @remarks Time O(1)
168
226
  *
169
- * The function creates a new BSTNode with the given key and value and returns it.
170
- * @param {K} key - The key parameter is of type K, which represents the type of the key for the node
171
- * being created.
172
- * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
173
- * value associated with the key in the node being created.
174
- * @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.
227
+ * @returns The key-to-comparable conversion function.
175
228
  */
176
- createNode(key, value) {
177
- return new BSTNode(key, this._isMapMode ? undefined : value);
229
+ get specifyComparable() {
230
+ return this._specifyComparable;
178
231
  }
179
232
  /**
180
- * Time Complexity: O(1)
181
- * Space Complexity: O(1)
233
+ * (Protected) Creates a new BST node.
234
+ * @remarks Time O(1), Space O(1)
182
235
  *
183
- * The function creates a new binary search tree with the specified options.
184
- * @param [options] - The `options` parameter is an optional object that allows you to customize the
185
- * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
186
- * following properties:
187
- * @returns a new instance of the BST class with the provided options.
236
+ * @param key - The key for the new node.
237
+ * @param [value] - The value for the new node (used if not in Map mode).
238
+ * @returns The newly created BSTNode.
188
239
  */
189
- createTree(options) {
190
- return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, specifyComparable: this._specifyComparable, toEntryFn: this._toEntryFn, isReverse: this._isReverse }, options));
240
+ _createNode(key, value) {
241
+ return new BSTNode(key, this._isMapMode ? undefined : value);
191
242
  }
192
243
  /**
193
- * Time Complexity: O(log n)
194
- * Space Complexity: O(log n)
244
+ * Ensures the input is a node. If it's a key or entry, it searches for the node.
245
+ * @remarks Time O(log N) (height of the tree), O(N) worst-case.
195
246
  *
196
- * The function ensures the existence of a node in a data structure and returns it, or undefined if
197
- * it doesn't exist.
198
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
199
- * `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,
200
- * entry, or raw element that needs to be ensured in the tree.
201
- * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
202
- * parameter that specifies the type of iteration to be used when ensuring a node. It has a default
203
- * value of `'ITERATIVE'`.
204
- * @returns The method is returning either the node that was ensured or `undefined` if the node could
205
- * not be ensured.
247
+ * @param keyNodeOrEntry - The item to resolve to a node.
248
+ * @param [iterationType=this.iterationType] - The traversal method to use if searching.
249
+ * @returns The resolved node, or undefined if not found.
206
250
  */
207
251
  ensureNode(keyNodeOrEntry, iterationType = this.iterationType) {
208
252
  var _a;
209
253
  return (_a = super.ensureNode(keyNodeOrEntry, iterationType)) !== null && _a !== void 0 ? _a : undefined;
210
254
  }
211
255
  /**
212
- * Time Complexity: O(1)
213
- * Space Complexity: O(1)
256
+ * Checks if the given item is a `BSTNode` instance.
257
+ * @remarks Time O(1), Space O(1)
214
258
  *
215
- * The function checks if the input is an instance of the BSTNode class.
216
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
217
- * `keyNodeOrEntry` can be of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
218
- * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
219
- * an instance of the `BSTNode` class.
259
+ * @param keyNodeOrEntry - The item to check.
260
+ * @returns True if it's a BSTNode, false otherwise.
220
261
  */
221
262
  isNode(keyNodeOrEntry) {
222
263
  return keyNodeOrEntry instanceof BSTNode;
223
264
  }
224
265
  /**
225
- * Time Complexity: O(1)
226
- * Space Complexity: O(1)
266
+ * Checks if the given key is valid (comparable).
267
+ * @remarks Time O(1)
227
268
  *
228
- * The function "override isValidKey" checks if a key is comparable based on a given comparator.
229
- * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
230
- * type `K`.
231
- * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
232
- * the result of the `isComparable` function with the condition `this._compare !==
233
- * this._DEFAULT_COMPARATOR`.
269
+ * @param key - The key to validate.
270
+ * @returns True if the key is valid, false otherwise.
234
271
  */
235
272
  isValidKey(key) {
236
273
  return (0, utils_1.isComparable)(key, this._specifyComparable !== undefined);
237
274
  }
238
275
  /**
239
- * Time Complexity: O(log n)
240
- * Space Complexity: O(log n)
276
+ * Performs a Depth-First Search (DFS) traversal.
277
+ * @remarks Time O(N), visits every node. Space O(log N) for the call/explicit stack. O(N) worst-case.
278
+ *
279
+ * @template C - The type of the callback function.
280
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
281
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
282
+ * @param [onlyOne=false] - If true, stops after the first callback.
283
+ * @param [startNode=this._root] - The node to start from.
284
+ * @param [iterationType=this.iterationType] - The traversal method.
285
+ * @returns An array of callback results.
286
+ */
287
+ dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
288
+ return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
289
+ }
290
+ /**
291
+ * Performs a Breadth-First Search (BFS) or Level-Order traversal.
292
+ * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue.
293
+ *
294
+ * @template C - The type of the callback function.
295
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
296
+ * @param [startNode=this._root] - The node to start from.
297
+ * @param [iterationType=this.iterationType] - The traversal method.
298
+ * @returns An array of callback results.
299
+ */
300
+ bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
301
+ return super.bfs(callback, startNode, iterationType, false);
302
+ }
303
+ /**
304
+ * Returns a 2D array of nodes, grouped by level.
305
+ * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
306
+ *
307
+ * @template C - The type of the callback function.
308
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
309
+ * @param [startNode=this._root] - The node to start from.
310
+ * @param [iterationType=this.iterationType] - The traversal method.
311
+ * @returns A 2D array of callback results.
312
+ */
313
+ listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
314
+ return super.listLevels(callback, startNode, iterationType, false);
315
+ }
316
+ /**
317
+ * Gets the first node matching a predicate.
318
+ * @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
319
+ *
320
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
321
+ * @param [startNode=this._root] - The node to start the search from.
322
+ * @param [iterationType=this.iterationType] - The traversal method.
323
+ * @returns The first matching node, or undefined if not found.
324
+ */
325
+ getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
326
+ var _a;
327
+ return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
328
+ }
329
+ /**
330
+ * Searches the tree for nodes matching a predicate, key, or range.
331
+ * @remarks This is an optimized search for a BST. If searching by key or range, it prunes branches.
332
+ * Time O(H + M) for key/range search (H=height, M=matches). O(N) for predicate search.
333
+ * Space O(log N) for the stack.
334
+ *
335
+ * @template C - The type of the callback function.
336
+ * @param keyNodeEntryOrPredicate - The key, node, entry, predicate, or range to search for.
337
+ * @param [onlyOne=false] - If true, stops after finding the first match.
338
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
339
+ * @param [startNode=this._root] - The node to start the search from.
340
+ * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
341
+ * @returns An array of results from the callback function for each matching node.
342
+ */
343
+ search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
344
+ if (keyNodeEntryOrPredicate === undefined)
345
+ return [];
346
+ if (keyNodeEntryOrPredicate === null)
347
+ return [];
348
+ startNode = this.ensureNode(startNode);
349
+ if (!startNode)
350
+ return [];
351
+ let predicate;
352
+ const isRange = this.isRange(keyNodeEntryOrPredicate);
353
+ if (isRange) {
354
+ predicate = node => {
355
+ if (!node)
356
+ return false;
357
+ return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
358
+ };
359
+ }
360
+ else {
361
+ predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
362
+ }
363
+ // Optimization: Pruning logic
364
+ const shouldVisitLeft = (cur) => {
365
+ if (!cur)
366
+ return false;
367
+ if (!this.isRealNode(cur.left))
368
+ return false;
369
+ if (isRange) {
370
+ // Range search: Only go left if the current key is >= the lower bound
371
+ const range = keyNodeEntryOrPredicate;
372
+ const leftS = this.isReverse ? range.high : range.low;
373
+ const leftI = this.isReverse ? range.includeHigh : range.includeLow;
374
+ return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
375
+ }
376
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
377
+ // Key search: Only go left if current key > target key
378
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
379
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;
380
+ }
381
+ return true; // Predicate search: must visit all
382
+ };
383
+ const shouldVisitRight = (cur) => {
384
+ if (!cur)
385
+ return false;
386
+ if (!this.isRealNode(cur.right))
387
+ return false;
388
+ if (isRange) {
389
+ // Range search: Only go right if current key <= upper bound
390
+ const range = keyNodeEntryOrPredicate;
391
+ const rightS = this.isReverse ? range.low : range.high;
392
+ const rightI = this.isReverse ? range.includeLow : range.includeHigh;
393
+ return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
394
+ }
395
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
396
+ // Key search: Only go right if current key < target key
397
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
398
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;
399
+ }
400
+ return true; // Predicate search: must visit all
401
+ };
402
+ return super._dfs(callback, 'IN', // In-order is efficient for range/key search
403
+ onlyOne, startNode, iterationType, false, shouldVisitLeft, shouldVisitRight, () => true, // shouldVisitRoot (always visit)
404
+ // shouldVisitRoot (always visit)
405
+ cur => !!cur && predicate(cur) // shouldProcessRoot (only process if predicate matches)
406
+ );
407
+ }
408
+ /**
409
+ * Performs an optimized search for nodes within a given key range.
410
+ * @remarks Time O(H + M), where H is tree height and M is the number of matches.
241
411
  *
242
- * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
243
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
244
- * `keyNodeOrEntry` can accept a value of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
245
- * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
246
- * key in the binary search tree. If provided, it will be stored in the node along with the key.
247
- * @returns a boolean value.
412
+ * @template C - The type of the callback function.
413
+ * @param range - A `Range` object or a `[low, high]` tuple.
414
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
415
+ * @param [startNode=this._root] - The node to start the search from.
416
+ * @param [iterationType=this.iterationType] - The traversal method.
417
+ * @returns An array of callback results.
418
+ */
419
+ rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
420
+ const searchRange = range instanceof common_1.Range ? range : new common_1.Range(range[0], range[1]);
421
+ return this.search(searchRange, false, callback, startNode, iterationType);
422
+ }
423
+ /**
424
+ * Adds a new node to the BST based on key comparison.
425
+ * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
426
+ *
427
+ * @param keyNodeOrEntry - The key, node, or entry to add.
428
+ * @param [value] - The value, if providing just a key.
429
+ * @returns True if the addition was successful, false otherwise.
248
430
  */
249
431
  add(keyNodeOrEntry, value) {
250
432
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
@@ -260,12 +442,14 @@ class BST extends binary_tree_1.BinaryTree {
260
442
  let current = this._root;
261
443
  while (current !== undefined) {
262
444
  if (this._compare(current.key, newNode.key) === 0) {
445
+ // Key exists, replace node
263
446
  this._replaceNode(current, newNode);
264
447
  if (this._isMapMode)
265
448
  this._setValue(current.key, newValue);
266
449
  return true;
267
450
  }
268
451
  else if (this._compare(current.key, newNode.key) > 0) {
452
+ // Go left
269
453
  if (current.left === undefined) {
270
454
  current.left = newNode;
271
455
  if (this._isMapMode)
@@ -277,6 +461,7 @@ class BST extends binary_tree_1.BinaryTree {
277
461
  current = current.left;
278
462
  }
279
463
  else {
464
+ // Go right
280
465
  if (current.right === undefined) {
281
466
  current.right = newNode;
282
467
  if (this._isMapMode)
@@ -291,49 +476,38 @@ class BST extends binary_tree_1.BinaryTree {
291
476
  return false;
292
477
  }
293
478
  /**
294
- * Time Complexity: O(k log n)
295
- * Space Complexity: O(k + log n)
296
- *
297
- * The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns
298
- * an array indicating whether each key or node was successfully inserted.
299
- * @param keysNodesEntriesOrRaws - An iterable containing keys, nodes, entries, or raw
300
- * elements to be added to the data structure.
301
- * @param [values] - An optional iterable of values to be associated with the keys or nodes being
302
- * added. If provided, the values will be assigned to the corresponding keys or nodes in the same
303
- * order. If not provided, undefined will be assigned as the value for each key or node.
304
- * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after
305
- * adding the elements. If set to true, the tree will be balanced using a binary search tree
306
- * algorithm. If set to false, the elements will be added without balancing the tree. The default
307
- * value is true.
308
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
309
- * specifies the type of iteration to use when adding multiple keys or nodes to the binary search
310
- * tree. It can have two possible values:
311
- * @returns The function `addMany` returns an array of booleans indicating whether each element was
312
- * successfully inserted into the data structure.
479
+ * Adds multiple items to the tree.
480
+ * @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced add).
481
+ * If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
482
+ * Space O(N) for sorting and recursion/iteration stack.
483
+ *
484
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
485
+ * @param [values] - An optional parallel iterable of values.
486
+ * @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
487
+ * @param [iterationType=this.iterationType] - The traversal method for balanced add (recursive or iterative).
488
+ * @returns An array of booleans indicating the success of each individual `add` operation.
313
489
  */
314
490
  addMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
315
491
  const inserted = [];
316
- let valuesIterator;
317
- if (values) {
318
- valuesIterator = values[Symbol.iterator]();
319
- }
492
+ const valuesIterator = values === null || values === void 0 ? void 0 : values[Symbol.iterator]();
320
493
  if (!isBalanceAdd) {
494
+ // Standard O(N*H) insertion
321
495
  for (let kve of keysNodesEntriesOrRaws) {
322
- const value = valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value;
496
+ const val = valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value;
323
497
  if (this.isRaw(kve))
324
498
  kve = this._toEntryFn(kve);
325
- inserted.push(this.add(kve, value));
499
+ inserted.push(this.add(kve, val));
326
500
  }
327
501
  return inserted;
328
502
  }
503
+ // Balanced O(N log N) insertion
329
504
  const realBTNExemplars = [];
330
505
  let i = 0;
331
506
  for (const kve of keysNodesEntriesOrRaws) {
332
- realBTNExemplars.push({ key: kve, value: valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value, orgIndex: i });
333
- i++;
507
+ realBTNExemplars.push({ key: kve, value: valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value, orgIndex: i++ });
334
508
  }
335
- let sorted = [];
336
- sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
509
+ // Sort items by key
510
+ const sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
337
511
  let keyA, keyB;
338
512
  if (this.isRaw(a))
339
513
  keyA = this._toEntryFn(a)[0];
@@ -341,29 +515,26 @@ class BST extends binary_tree_1.BinaryTree {
341
515
  keyA = a[0];
342
516
  else if (this.isRealNode(a))
343
517
  keyA = a.key;
344
- else {
518
+ else
345
519
  keyA = a;
346
- }
347
520
  if (this.isRaw(b))
348
521
  keyB = this._toEntryFn(b)[0];
349
522
  else if (this.isEntry(b))
350
523
  keyB = b[0];
351
524
  else if (this.isRealNode(b))
352
525
  keyB = b.key;
353
- else {
526
+ else
354
527
  keyB = b;
355
- }
356
- if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
528
+ if (keyA != null && keyB != null)
357
529
  return this._compare(keyA, keyB);
358
- }
359
530
  return 0;
360
531
  });
532
+ // Recursive balanced build
361
533
  const _dfs = (arr) => {
362
534
  if (arr.length === 0)
363
535
  return;
364
536
  const mid = Math.floor((arr.length - 1) / 2);
365
- const { key, value } = arr[mid];
366
- const { orgIndex } = arr[mid];
537
+ const { key, value, orgIndex } = arr[mid];
367
538
  if (this.isRaw(key)) {
368
539
  const entry = this._toEntryFn(key);
369
540
  inserted[orgIndex] = this.add(entry);
@@ -374,281 +545,58 @@ class BST extends binary_tree_1.BinaryTree {
374
545
  _dfs(arr.slice(0, mid));
375
546
  _dfs(arr.slice(mid + 1));
376
547
  };
548
+ // Iterative balanced build
377
549
  const _iterate = () => {
378
550
  const n = sorted.length;
379
551
  const stack = [[0, n - 1]];
380
552
  while (stack.length > 0) {
381
553
  const popped = stack.pop();
382
- if (popped) {
383
- const [l, r] = popped;
384
- if (l <= r) {
385
- const m = l + Math.floor((r - l) / 2);
386
- const { key, value } = sorted[m];
387
- const { orgIndex } = sorted[m];
388
- if (this.isRaw(key)) {
389
- const entry = this._toEntryFn(key);
390
- inserted[orgIndex] = this.add(entry);
391
- }
392
- else {
393
- inserted[orgIndex] = this.add(key, value);
394
- }
395
- stack.push([m + 1, r]);
396
- stack.push([l, m - 1]);
397
- }
554
+ if (!popped)
555
+ continue;
556
+ const [l, r] = popped;
557
+ if (l > r)
558
+ continue;
559
+ const m = l + Math.floor((r - l) / 2);
560
+ const { key, value, orgIndex } = sorted[m];
561
+ if (this.isRaw(key)) {
562
+ const entry = this._toEntryFn(key);
563
+ inserted[orgIndex] = this.add(entry);
398
564
  }
565
+ else {
566
+ inserted[orgIndex] = this.add(key, value);
567
+ }
568
+ stack.push([m + 1, r]);
569
+ stack.push([l, m - 1]);
399
570
  }
400
571
  };
401
- if (iterationType === 'RECURSIVE') {
572
+ if (iterationType === 'RECURSIVE')
402
573
  _dfs(sorted);
403
- }
404
- else {
574
+ else
405
575
  _iterate();
406
- }
407
576
  return inserted;
408
577
  }
409
578
  /**
410
- * Time Complexity: O(log n)
411
- * Space Complexity: O(k + log n)
412
- *
413
- * The function `search` in TypeScript overrides the search behavior in a binary tree structure based
414
- * on specified criteria.
415
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The
416
- * `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the
417
- * following types:
418
- * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
419
- * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
420
- * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
421
- * @param {C} callback - The `callback` parameter in the `override search` function is a function
422
- * that will be called on each node that matches the search criteria. It is of type `C`, which
423
- * extends `NodeCallback<BSTNode<K, V> | null>`. The callback function should accept a node of type `BSTNode<K, V>` as its
424
- * argument and
425
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `override search`
426
- * method represents the node from which the search operation will begin. It is the starting point
427
- * for searching within the tree data structure. The method ensures that the `startNode` is a valid
428
- * node before proceeding with the search operation. If the `
429
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
430
- * function determines the type of iteration to be used during the search operation. It can have two
431
- * possible values:
432
- * @returns The `override search` method returns an array of values that match the search criteria
433
- * specified by the input parameters. The method performs a search operation on a binary tree
434
- * structure based on the provided key, predicate, and other options. The search results are
435
- * collected in an array and returned as the output of the method.
436
- */
437
- search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
438
- if (keyNodeEntryOrPredicate === undefined)
439
- return [];
440
- if (keyNodeEntryOrPredicate === null)
441
- return [];
442
- startNode = this.ensureNode(startNode);
443
- if (!startNode)
444
- return [];
445
- let predicate;
446
- const isRange = this.isRange(keyNodeEntryOrPredicate);
447
- // Set predicate based on parameter type
448
- if (isRange) {
449
- predicate = node => {
450
- if (!node)
451
- return false;
452
- return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
453
- };
454
- }
455
- else {
456
- predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
457
- }
458
- const shouldVisitLeft = (cur) => {
459
- if (!cur)
460
- return false;
461
- if (!this.isRealNode(cur.left))
462
- return false;
463
- if (isRange) {
464
- const range = keyNodeEntryOrPredicate;
465
- const leftS = this.isReverse ? range.high : range.low;
466
- const leftI = this.isReverse ? range.includeHigh : range.includeLow;
467
- return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
468
- }
469
- if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
470
- const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
471
- return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;
472
- }
473
- return true;
474
- };
475
- const shouldVisitRight = (cur) => {
476
- if (!cur)
477
- return false;
478
- if (!this.isRealNode(cur.right))
479
- return false;
480
- if (isRange) {
481
- const range = keyNodeEntryOrPredicate;
482
- const rightS = this.isReverse ? range.low : range.high;
483
- const rightI = this.isReverse ? range.includeLow : range.includeLow;
484
- return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
485
- }
486
- if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
487
- const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
488
- return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;
489
- }
490
- return true;
491
- };
492
- return super._dfs(callback, 'IN', onlyOne, startNode, iterationType, false, shouldVisitLeft, shouldVisitRight, () => true, cur => {
493
- if (cur)
494
- return predicate(cur);
495
- return false;
496
- });
497
- }
498
- /**
499
- * Time Complexity: O(log n)
500
- * Space Complexity: O(k + log n)
501
- *
502
- * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
503
- * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
504
- * either a `Range` object or an array of two elements representing the range boundaries.
505
- * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
506
- * function that is used to process each node that is found within the specified range during the
507
- * search operation. It is of type `NodeCallback<BSTNode<K, V> | null>`, where `BSTNode<K, V>` is the type of nodes in the
508
- * data structure.
509
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `rangeSearch`
510
- * function represents the node from which the search for nodes within the specified range will
511
- * begin. It is the starting point for the range search operation.
512
- * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
513
- * is used to specify the type of iteration to be performed during the search operation. It has a
514
- * default value of `this.iterationType`, which suggests that it is likely a property of the class or
515
- * object that the `rangeSearch`
516
- * @returns The `rangeSearch` function is returning the result of calling the `search` method with
517
- * the specified parameters.
518
- */
519
- rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
520
- const searchRange = range instanceof common_1.Range ? range : new common_1.Range(range[0], range[1]);
521
- return this.search(searchRange, false, callback, startNode, iterationType);
522
- }
523
- /**
524
- * Time Complexity: O(log n)
525
- * Space Complexity: O(log n)
526
- *
527
- * This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.
528
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`
529
- * parameter can be of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `R`, or `NodePredicate<BSTNode<K, V>>`.
530
- * @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method
531
- * is used to specify the starting point for searching nodes in the binary search tree. If no
532
- * specific starting point is provided, the default value is set to `this._root`, which is the root
533
- * node of the binary search tree.
534
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a
535
- * parameter that specifies the type of iteration to be used. It has a default value of
536
- * `this.iterationType`, which means it will use the iteration type defined in the class instance if
537
- * no value is provided when calling the method.
538
- * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).
539
- * It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at
540
- * the specified root node (`startNode`) and using the specified iteration type. The method then
541
- * returns the first node found or `undefined` if no node is found.
542
- */
543
- getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
544
- var _a;
545
- return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
546
- }
547
- /**
548
- * Time complexity: O(n)
549
- * Space complexity: O(n)
550
- *
551
- * The function `dfs` in TypeScript overrides the base class method with default parameters and
552
- * returns the result of the super class `dfs` method.
553
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
554
- * visited during the Depth-First Search traversal. It is a generic type `C` that extends the
555
- * `NodeCallback` interface for `BSTNode<K, V>`. The default value for `callback` is `this._
556
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `override dfs` method
557
- * specifies the order in which the Depth-First Search (DFS) traversal should be performed on the
558
- * Binary Search Tree (BST). The possible values for the `pattern` parameter are:
559
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `override dfs` method is a
560
- * boolean flag that indicates whether you want to stop the depth-first search traversal after
561
- * finding the first matching node or continue searching for all matching nodes. If `onlyOne` is set
562
- * to `true`, the traversal will stop after finding
563
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} startNode -
564
- * The `startNode` parameter in the `override dfs` method can be one of the following types:
565
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override dfs` method
566
- * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
567
- * Binary Search Tree (BST). It is used to determine the order in which nodes are visited during the
568
- * traversal. The possible values for `
569
- * @returns The `override` function is returning the result of calling the `dfs` method from the
570
- * superclass, with the provided arguments `callback`, `pattern`, `onlyOne`, `startNode`, and
571
- * `iterationType`. The return type is an array of the return type of the callback function `C`.
572
- */
573
- dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
574
- return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
575
- }
576
- /**
577
- * Time complexity: O(n)
578
- * Space complexity: O(n)
579
- *
580
- * The function overrides the breadth-first search method and returns an array of the return types of
581
- * the callback function.
582
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
583
- * visited during the breadth-first search. It should take a single argument, which is the current
584
- * node being visited, and it can return a value of any type.
585
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
586
- * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
587
- * object. If no value is provided, the default value is the root of the tree.
588
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
589
- * of iteration to be performed during the breadth-first search (BFS) traversal. It can have one of
590
- * the following values:
591
- * @returns an array of the return type of the callback function.
592
- */
593
- bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
594
- return super.bfs(callback, startNode, iterationType, false);
595
- }
596
- /**
597
- * Time complexity: O(n)
598
- * Space complexity: O(n)
579
+ * Traverses the tree and returns nodes that are lesser or greater than a target node.
580
+ * @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N).
599
581
  *
600
- * The function overrides the listLevels method from the superclass and returns an array of arrays
601
- * containing the results of the callback function applied to each level of the tree.
602
- * @param {C} callback - The `callback` parameter is a generic type `C` that extends
603
- * `NodeCallback<BSTNode<K, V> | null>`. It represents a callback function that will be called for each node in the
604
- * tree during the iteration process.
605
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
606
- * point for listing the levels of the binary tree. It can be either a root node of the tree, a
607
- * key-value pair representing a node in the tree, or a key representing a node in the tree. If no
608
- * value is provided, the root of
609
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
610
- * of iteration to be performed on the tree. It can have one of the following values:
611
- * @returns The method is returning a two-dimensional array of the return type of the callback
612
- * function.
613
- */
614
- listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
615
- return super.listLevels(callback, startNode, iterationType, false);
616
- }
617
- /**
618
- * Time complexity: O(n)
619
- * Space complexity: O(n)
620
- *
621
- * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to
622
- * each node that meets a certain condition based on a target node and a comparison value.
623
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
624
- * that meets the condition specified by the `lesserOrGreater` parameter. It takes a single argument,
625
- * which is the current node being traversed, and returns a value of any type.
626
- * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
627
- * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
628
- * 0, or 1, where:
629
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } targetNode - The `targetNode` parameter is the node in
630
- * the binary tree that you want to start traversing from. It can be specified either by providing
631
- * the key of the node, the node itself, or an entry containing the key and value of the node. If no
632
- * `targetNode` is provided,
633
- * @param {IterationType} iterationType - The `iterationType` parameter determines the type of
634
- * traversal to be performed on the binary tree. It can have two possible values:
635
- * @returns The function `lesserOrGreaterTraverse` returns an array of values of type
636
- * `ReturnType<C>`, which is the return type of the callback function passed as an argument.
582
+ * @template C - The type of the callback function.
583
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on matching nodes.
584
+ * @param [lesserOrGreater=-1] - -1 for lesser, 1 for greater, 0 for equal.
585
+ * @param [targetNode=this._root] - The node to compare against.
586
+ * @param [iterationType=this.iterationType] - The traversal method.
587
+ * @returns An array of callback results.
637
588
  */
638
589
  lesserOrGreaterTraverse(callback = this._DEFAULT_NODE_CALLBACK, lesserOrGreater = -1, targetNode = this._root, iterationType = this.iterationType) {
639
590
  const targetNodeEnsured = this.ensureNode(targetNode);
640
591
  const ans = [];
641
- if (!this._root)
642
- return ans;
643
- if (!targetNodeEnsured)
592
+ if (!this._root || !targetNodeEnsured)
644
593
  return ans;
645
594
  const targetKey = targetNodeEnsured.key;
646
595
  if (iterationType === 'RECURSIVE') {
647
596
  const dfs = (cur) => {
648
597
  const compared = this._compare(cur.key, targetKey);
649
- if (Math.sign(compared) === lesserOrGreater)
598
+ if (Math.sign(compared) == lesserOrGreater)
650
599
  ans.push(callback(cur));
651
- // TODO here can be optimized to O(log n)
652
600
  if (this.isRealNode(cur.left))
653
601
  dfs(cur.left);
654
602
  if (this.isRealNode(cur.right))
@@ -663,7 +611,7 @@ class BST extends binary_tree_1.BinaryTree {
663
611
  const cur = queue.shift();
664
612
  if (this.isRealNode(cur)) {
665
613
  const compared = this._compare(cur.key, targetKey);
666
- if (Math.sign(compared) === lesserOrGreater)
614
+ if (Math.sign(compared) == lesserOrGreater)
667
615
  ans.push(callback(cur));
668
616
  if (this.isRealNode(cur.left))
669
617
  queue.push(cur.left);
@@ -675,80 +623,54 @@ class BST extends binary_tree_1.BinaryTree {
675
623
  }
676
624
  }
677
625
  /**
678
- * Time complexity: O(n)
679
- * Space complexity: O(n)
626
+ * Rebuilds the tree to be perfectly balanced.
627
+ * @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
680
628
  *
681
- * The `perfectlyBalance` function takes an optional `iterationType` parameter and returns `true` if
682
- * the binary search tree is perfectly balanced, otherwise it returns `false`.
683
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
684
- * specifies the type of iteration to use when building a balanced binary search tree. It has a
685
- * default value of `this.iterationType`, which means it will use the iteration type specified in the
686
- * current instance of the class.
687
- * @returns The function `perfectlyBalance` returns a boolean value.
629
+ * @param [iterationType=this.iterationType] - The traversal method for the initial node export.
630
+ * @returns True if successful, false if the tree was empty.
688
631
  */
689
632
  perfectlyBalance(iterationType = this.iterationType) {
690
- const sorted = this.dfs(node => node, 'IN'), n = sorted.length;
633
+ const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
634
+ const n = nodes.length;
691
635
  this._clearNodes();
692
- if (sorted.length < 1)
636
+ if (n === 0)
693
637
  return false;
694
- if (iterationType === 'RECURSIVE') {
695
- const buildBalanceBST = (l, r) => {
696
- if (l > r)
697
- return;
698
- const m = l + Math.floor((r - l) / 2);
699
- const midNode = sorted[m];
700
- if (this._isMapMode && midNode !== null)
701
- this.add(midNode.key);
702
- else if (midNode !== null)
703
- this.add([midNode.key, midNode.value]);
704
- buildBalanceBST(l, m - 1);
705
- buildBalanceBST(m + 1, r);
706
- };
707
- buildBalanceBST(0, n - 1);
708
- return true;
709
- }
710
- else {
711
- const stack = [[0, n - 1]];
712
- while (stack.length > 0) {
713
- const popped = stack.pop();
714
- if (popped) {
715
- const [l, r] = popped;
716
- if (l <= r) {
717
- const m = l + Math.floor((r - l) / 2);
718
- const midNode = sorted[m];
719
- if (this._isMapMode && midNode !== null)
720
- this.add(midNode.key);
721
- else if (midNode !== null)
722
- this.add([midNode.key, midNode.value]);
723
- stack.push([m + 1, r]);
724
- stack.push([l, m - 1]);
725
- }
726
- }
727
- }
728
- return true;
729
- }
638
+ // Build balanced tree from sorted array
639
+ const build = (l, r, parent) => {
640
+ if (l > r)
641
+ return undefined;
642
+ const m = l + ((r - l) >> 1);
643
+ const root = nodes[m];
644
+ const leftChild = build(l, m - 1, root);
645
+ const rightChild = build(m + 1, r, root);
646
+ root.left = leftChild;
647
+ root.right = rightChild;
648
+ root.parent = parent;
649
+ return root;
650
+ };
651
+ const newRoot = build(0, n - 1, undefined);
652
+ this._setRoot(newRoot);
653
+ this._size = n;
654
+ return true;
730
655
  }
731
656
  /**
732
- * Time Complexity: O(n)
733
- * Space Complexity: O(log n)
657
+ * Checks if the tree meets the AVL balance condition (height difference <= 1).
658
+ * @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map.
734
659
  *
735
- * The function `isAVLBalanced` checks if a binary tree is AVL balanced using either a recursive or
736
- * iterative approach.
737
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
738
- * specifies the type of iteration to use when checking if the AVL tree is balanced. It has a default
739
- * value of `this.iterationType`, which means it will use the iteration type specified in the current
740
- * instance of the AVL tree.
741
- * @returns a boolean value.
660
+ * @param [iterationType=this.iterationType] - The traversal method.
661
+ * @returns True if the tree is AVL balanced, false otherwise.
742
662
  */
743
663
  isAVLBalanced(iterationType = this.iterationType) {
744
664
  if (!this._root)
745
665
  return true;
746
666
  let balanced = true;
747
667
  if (iterationType === 'RECURSIVE') {
668
+ // Recursive height check
748
669
  const _height = (cur) => {
749
670
  if (!cur)
750
671
  return 0;
751
- const leftHeight = _height(cur.left), rightHeight = _height(cur.right);
672
+ const leftHeight = _height(cur.left);
673
+ const rightHeight = _height(cur.right);
752
674
  if (Math.abs(leftHeight - rightHeight) > 1)
753
675
  balanced = false;
754
676
  return Math.max(leftHeight, rightHeight) + 1;
@@ -756,6 +678,7 @@ class BST extends binary_tree_1.BinaryTree {
756
678
  _height(this._root);
757
679
  }
758
680
  else {
681
+ // Iterative post-order height check
759
682
  const stack = [];
760
683
  let node = this._root, last = undefined;
761
684
  const depths = new Map();
@@ -787,93 +710,194 @@ class BST extends binary_tree_1.BinaryTree {
787
710
  return balanced;
788
711
  }
789
712
  /**
790
- * Time complexity: O(n)
791
- * Space complexity: O(n)
792
- *
793
- * The `map` function in TypeScript overrides the default map behavior for a binary search tree by
794
- * applying a callback function to each entry and creating a new tree with the results.
795
- * @param callback - A function that will be called for each entry in the BST. It takes four
796
- * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to
797
- * the BST itself.
798
- * @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,
799
- * MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary
800
- * Search Tree (BST) being created in the `map` method. These options could include configuration
801
- * @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify
802
- * the value of `this` that should be used when executing the `callback` function. It allows you to
803
- * set the context or scope in which the callback function will be called. This can be useful when
804
- * you want
805
- * @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries
806
- * transformed by the provided callback function.
713
+ * Creates a new BST by mapping each [key, value] pair to a new entry.
714
+ * @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
715
+ * Space O(N) for the new tree.
716
+ *
717
+ * @template MK - New key type.
718
+ * @template MV - New value type.
719
+ * @template MR - New raw type.
720
+ * @param callback - A function to map each [key, value] pair.
721
+ * @param [options] - Options for the new BST.
722
+ * @param [thisArg] - `this` context for the callback.
723
+ * @returns A new, mapped BST.
807
724
  */
808
725
  map(callback, options, thisArg) {
809
- const newTree = new BST([], options);
726
+ const out = this._createLike([], options);
810
727
  let index = 0;
728
+ // Iterates in-order
811
729
  for (const [key, value] of this) {
812
- newTree.add(callback.call(thisArg, key, value, index++, this));
730
+ out.add(callback.call(thisArg, key, value, index++, this));
813
731
  }
814
- return newTree;
732
+ return out;
815
733
  }
816
734
  /**
817
- * Time complexity: O(n)
818
- * Space complexity: O(n)
735
+ * Deletes the first node found that satisfies the predicate.
736
+ * @remarks Performs an in-order traversal. Time O(N) worst-case (O(log N) to find + O(log N) to delete). Space O(log N) for stack.
819
737
  *
820
- * The function `clone` overrides the default cloning behavior to create a deep copy of a tree
821
- * structure.
822
- * @returns The `cloned` object is being returned.
738
+ * @param predicate - A function to test each [key, value] pair.
739
+ * @returns True if a node was deleted, false otherwise.
823
740
  */
824
- clone() {
825
- const cloned = this.createTree();
826
- this._clone(cloned);
827
- return cloned;
741
+ deleteWhere(predicate) {
742
+ const stack = [];
743
+ let cur = this._root;
744
+ let index = 0;
745
+ // In-order traversal to find the node
746
+ while (stack.length > 0 || cur !== undefined) {
747
+ while (cur !== undefined && cur !== null) {
748
+ stack.push(cur);
749
+ cur = cur.left;
750
+ }
751
+ const node = stack.pop();
752
+ if (!node)
753
+ break;
754
+ const key = node.key;
755
+ const val = node.value;
756
+ if (predicate(key, val, index++, this)) {
757
+ return this._deleteByKey(key); // Found, now delete
758
+ }
759
+ cur = node.right;
760
+ }
761
+ return false;
762
+ }
763
+ /**
764
+ * (Protected) Creates a new, empty instance of the same BST constructor.
765
+ * @remarks Time O(1)
766
+ *
767
+ * @template TK, TV, TR - Generic types for the new instance.
768
+ * @param [options] - Options for the new BST.
769
+ * @returns A new, empty BST.
770
+ */
771
+ _createInstance(options) {
772
+ const Ctor = this.constructor;
773
+ return new Ctor([], Object.assign(Object.assign({}, this._snapshotOptions()), (options !== null && options !== void 0 ? options : {})));
828
774
  }
829
775
  /**
830
- * Time Complexity: O(1)
831
- * Space Complexity: O(1)
776
+ * (Protected) Creates a new instance of the same BST constructor, potentially with different generic types.
777
+ * @remarks Time O(N log N) or O(N^2) (from constructor) due to processing the iterable.
832
778
  *
833
- * The function overrides a method and converts a key, value pair or entry or raw element to a node.
834
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - A variable that can be of
835
- * type R or K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined . It represents either a key, a node, an entry, or a raw
836
- * element.
837
- * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
838
- * value associated with a key in a key-value pair.
839
- * @returns either a BSTNode<K, V> object or undefined.
779
+ * @template TK, TV, TR - Generic types for the new instance.
780
+ * @param [iter=[]] - An iterable to populate the new BST.
781
+ * @param [options] - Options for the new BST.
782
+ * @returns A new BST.
783
+ */
784
+ _createLike(iter = [], options) {
785
+ const Ctor = this.constructor;
786
+ return new Ctor(iter, Object.assign(Object.assign({}, this._snapshotOptions()), (options !== null && options !== void 0 ? options : {})));
787
+ }
788
+ /**
789
+ * (Protected) Snapshots the current BST's configuration options.
790
+ * @remarks Time O(1)
791
+ *
792
+ * @template TK, TV, TR - Generic types for the options.
793
+ * @returns The options object.
794
+ */
795
+ _snapshotOptions() {
796
+ return Object.assign(Object.assign({}, super._snapshotOptions()), { specifyComparable: this.specifyComparable, isReverse: this.isReverse });
797
+ }
798
+ /**
799
+ * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
800
+ * @remarks Time O(1)
801
+ *
802
+ * @param keyNodeOrEntry - The input item.
803
+ * @param [value] - An optional value (used if input is just a key).
804
+ * @returns A tuple of [node, value].
840
805
  */
841
806
  _keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
842
807
  const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
843
808
  if (node === null)
844
- return [undefined, undefined];
809
+ return [undefined, undefined]; // BST handles null differently (as undefined)
845
810
  return [node, value !== null && value !== void 0 ? value : entryValue];
846
811
  }
847
812
  /**
848
- * Time Complexity: O(1)
849
- * Space Complexity: O(1)
813
+ * (Protected) Sets the root node and clears its parent reference.
814
+ * @remarks Time O(1)
850
815
  *
851
- * The function sets the root of a tree-like structure and updates the parent property of the new
852
- * root.
853
- * @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.
816
+ * @param v - The node to set as root.
854
817
  */
855
818
  _setRoot(v) {
856
- if (v) {
819
+ if (v)
857
820
  v.parent = undefined;
858
- }
859
821
  this._root = v;
860
822
  }
861
823
  /**
862
- * Time Complexity: O(1)
863
- * Space Complexity: O(1)
824
+ * (Protected) Compares two keys using the tree's comparator and reverse setting.
825
+ * @remarks Time O(1) (or O(C) if `specifyComparable` is used).
864
826
  *
865
- * The _compare function compares two values using a specified comparator function and optionally
866
- * reverses the result.
867
- * @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the
868
- * `_compare` method.
869
- * @param {K} b - The parameter `b` in the `_compare` function is of type `K`.
870
- * @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`
871
- * is true, it returns the negation of the result of calling the `_comparator` function with
872
- * arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the
873
- * `_comparator` function with arguments `a` and `b`.
827
+ * @param a - The first key.
828
+ * @param b - The second key.
829
+ * @returns A number (1, -1, or 0) representing the comparison.
874
830
  */
875
831
  _compare(a, b) {
876
832
  return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
877
833
  }
834
+ /**
835
+ * (Private) Deletes a node by its key.
836
+ * @remarks Standard BST deletion algorithm. Time O(log N), O(N) worst-case. Space O(1).
837
+ *
838
+ * @param key - The key of the node to delete.
839
+ * @returns True if the node was found and deleted, false otherwise.
840
+ */
841
+ _deleteByKey(key) {
842
+ var _a;
843
+ let node = this._root;
844
+ // 1. Find the node
845
+ while (node) {
846
+ const cmp = this._compare(node.key, key);
847
+ if (cmp === 0)
848
+ break;
849
+ node = cmp > 0 ? node.left : node.right;
850
+ }
851
+ if (!node)
852
+ return false; // Not found
853
+ // Helper to replace node `u` with node `v`
854
+ const transplant = (u, v) => {
855
+ const p = u === null || u === void 0 ? void 0 : u.parent;
856
+ if (!p) {
857
+ this._setRoot(v);
858
+ }
859
+ else if (p.left === u) {
860
+ p.left = v;
861
+ }
862
+ else {
863
+ p.right = v;
864
+ }
865
+ if (v)
866
+ v.parent = p;
867
+ };
868
+ // Helper to find the minimum node in a subtree
869
+ const minNode = (x) => {
870
+ if (!x)
871
+ return undefined;
872
+ while (x.left !== undefined && x.left !== null)
873
+ x = x.left;
874
+ return x;
875
+ };
876
+ // 2. Perform deletion
877
+ if (node.left === undefined) {
878
+ // Case 1: No left child
879
+ transplant(node, node.right);
880
+ }
881
+ else if (node.right === undefined) {
882
+ // Case 2: No right child
883
+ transplant(node, node.left);
884
+ }
885
+ else {
886
+ // Case 3: Two children
887
+ const succ = minNode(node.right); // Find successor
888
+ if (succ.parent !== node) {
889
+ transplant(succ, succ.right);
890
+ succ.right = node.right;
891
+ if (succ.right)
892
+ succ.right.parent = succ;
893
+ }
894
+ transplant(node, succ);
895
+ succ.left = node.left;
896
+ if (succ.left)
897
+ succ.left.parent = succ;
898
+ }
899
+ this._size = Math.max(0, ((_a = this._size) !== null && _a !== void 0 ? _a : 0) - 1);
900
+ return true;
901
+ }
878
902
  }
879
903
  exports.BST = BST;