graph-typed 1.47.6 → 1.47.7

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 (28) hide show
  1. package/dist/data-structures/binary-tree/avl-tree.d.ts +40 -22
  2. package/dist/data-structures/binary-tree/avl-tree.js +45 -36
  3. package/dist/data-structures/binary-tree/binary-tree.d.ts +105 -113
  4. package/dist/data-structures/binary-tree/binary-tree.js +133 -119
  5. package/dist/data-structures/binary-tree/bst.d.ts +53 -44
  6. package/dist/data-structures/binary-tree/bst.js +137 -154
  7. package/dist/data-structures/binary-tree/rb-tree.d.ts +48 -15
  8. package/dist/data-structures/binary-tree/rb-tree.js +70 -33
  9. package/dist/data-structures/binary-tree/tree-multimap.d.ts +26 -37
  10. package/dist/data-structures/binary-tree/tree-multimap.js +58 -137
  11. package/dist/data-structures/hash/hash-map.d.ts +2 -6
  12. package/dist/data-structures/hash/hash-map.js +5 -8
  13. package/dist/data-structures/trie/trie.d.ts +3 -0
  14. package/dist/data-structures/trie/trie.js +19 -4
  15. package/dist/interfaces/binary-tree.d.ts +3 -3
  16. package/dist/types/common.d.ts +6 -1
  17. package/dist/types/data-structures/hash/hash-map.d.ts +1 -2
  18. package/package.json +2 -2
  19. package/src/data-structures/binary-tree/avl-tree.ts +59 -39
  20. package/src/data-structures/binary-tree/binary-tree.ts +192 -180
  21. package/src/data-structures/binary-tree/bst.ts +157 -154
  22. package/src/data-structures/binary-tree/rb-tree.ts +78 -37
  23. package/src/data-structures/binary-tree/tree-multimap.ts +67 -145
  24. package/src/data-structures/hash/hash-map.ts +8 -8
  25. package/src/data-structures/trie/trie.ts +23 -4
  26. package/src/interfaces/binary-tree.ts +3 -3
  27. package/src/types/common.ts +11 -1
  28. package/src/types/data-structures/hash/hash-map.ts +1 -2
@@ -5,8 +5,18 @@
5
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import type { BSTNested, BSTNodeNested, BSTOptions, BTNCallback, BTNKey, Comparator } from '../../types';
9
- import { CP, IterableEntriesOrKeys, IterationType } from '../../types';
8
+ import type {
9
+ BSTNested,
10
+ BSTNodeKeyOrNode,
11
+ BSTNodeNested,
12
+ BSTOptions,
13
+ BTNCallback,
14
+ BTNKey,
15
+ BTNodeExemplar,
16
+ BTNodePureExemplar,
17
+ Comparator
18
+ } from '../../types';
19
+ import { CP, IterationType } from '../../types';
10
20
  import { BinaryTree, BinaryTreeNode } from './binary-tree';
11
21
  import { IBinaryTree } from '../../interfaces';
12
22
  import { Queue } from '../queue';
@@ -62,16 +72,29 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
62
72
  }
63
73
  }
64
74
 
75
+ /**
76
+ * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
77
+ * 2. Unique Keys: No duplicate keys in a standard BST.
78
+ * 3. Efficient Search: Enables quick search, minimum, and maximum operations.
79
+ * 4. Inorder Traversal: Yields nodes in ascending order.
80
+ * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
81
+ * 6. Balance Variability: Can become unbalanced; special types maintain balance.
82
+ * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
83
+ */
65
84
  export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>, TREE extends BST<V, N, TREE> = BST<V, N, BSTNested<V, N>>>
66
85
  extends BinaryTree<V, N, TREE>
67
86
  implements IBinaryTree<V, N, TREE> {
68
87
 
88
+
69
89
  /**
70
- * The constructor function initializes a binary search tree with an optional comparator function.
71
- * @param {BSTOptions} [options] - An optional object that contains additional configuration options
72
- * for the binary search tree.
90
+ * This is the constructor function for a binary search tree class in TypeScript, which initializes
91
+ * the tree with optional elements and options.
92
+ * @param [elements] - An optional iterable of BTNodeExemplar objects that will be added to the
93
+ * binary search tree.
94
+ * @param [options] - The `options` parameter is an optional object that can contain additional
95
+ * configuration options for the binary search tree. It can have the following properties:
73
96
  */
74
- constructor(elements?: IterableEntriesOrKeys<V>, options?: Partial<BSTOptions>) {
97
+ constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BSTOptions>) {
75
98
  super([], options);
76
99
 
77
100
  if (options) {
@@ -82,14 +105,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
82
105
  }
83
106
 
84
107
  this._root = undefined;
85
- if (elements) this.init(elements);
108
+
109
+ if (elements) this.addMany(elements);
86
110
  }
87
111
 
88
112
  protected override _root?: N;
89
113
 
90
- /**
91
- * Get the root node of the binary tree.
92
- */
93
114
  override get root(): N | undefined {
94
115
  return this._root;
95
116
  }
@@ -108,6 +129,13 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
108
129
  return new BSTNode<V, N>(key, value) as N;
109
130
  }
110
131
 
132
+ /**
133
+ * The function creates a new binary search tree with the specified options.
134
+ * @param [options] - The `options` parameter is an optional object that allows you to customize the
135
+ * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which is a type
136
+ * that defines various options for creating a binary search tree.
137
+ * @returns a new instance of the BST class with the specified options.
138
+ */
111
139
  override createTree(options?: Partial<BSTOptions>): TREE {
112
140
  return new BST<V, N, TREE>([], {
113
141
  iterationType: this.iterationType,
@@ -115,162 +143,154 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
115
143
  }) as TREE;
116
144
  }
117
145
 
146
+ /**
147
+ * Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
148
+ * Space Complexity: O(1) - Constant space is used.
149
+ */
150
+
118
151
  /**
119
152
  * Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
120
153
  * Space Complexity: O(1) - Constant space is used.
121
154
  *
122
- * The `add` function adds a new node to a binary search tree based on the provided key and value.
123
- * @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the
124
- * following types:
125
- * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
126
- * key or node being added to the binary search tree.
127
- * @returns The method `add` returns a node (`N`) that was inserted into the binary search tree. If
128
- * no node was inserted, it returns `undefined`.
155
+ * The `add` function adds a new node to a binary search tree, either by key or by providing a node
156
+ * object.
157
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
158
+ * @returns The method returns either the newly added node (`newNode`) or `undefined` if the input
159
+ * (`keyOrNodeOrEntry`) is null, undefined, or does not match any of the expected types.
129
160
  */
130
- override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
131
- if (keyOrNode === null) return undefined;
132
- // TODO support node as a parameter
133
- let inserted: N | undefined;
161
+ override add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | undefined {
162
+ if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) {
163
+ return undefined;
164
+ }
165
+
134
166
  let newNode: N | undefined;
135
- if (keyOrNode instanceof BSTNode) {
136
- newNode = keyOrNode;
137
- } else if (this.isNodeKey(keyOrNode)) {
138
- newNode = this.createNode(keyOrNode, value);
167
+ if (keyOrNodeOrEntry instanceof BSTNode) {
168
+ newNode = keyOrNodeOrEntry;
169
+ } else if (this.isNodeKey(keyOrNodeOrEntry)) {
170
+ newNode = this.createNode(keyOrNodeOrEntry);
171
+ } else if (this.isEntry(keyOrNodeOrEntry)) {
172
+ const [key, value] = keyOrNodeOrEntry;
173
+ if (key === undefined || key === null) {
174
+ return;
175
+ } else {
176
+ newNode = this.createNode(key, value);
177
+ }
139
178
  } else {
140
- newNode = undefined;
179
+ return;
141
180
  }
181
+
142
182
  if (this.root === undefined) {
143
183
  this._setRoot(newNode);
144
- this._size = this.size + 1;
145
- inserted = this.root;
146
- } else {
147
- let cur = this.root;
148
- let traversing = true;
149
- while (traversing) {
150
- if (cur !== undefined && newNode !== undefined) {
151
- if (this._compare(cur.key, newNode.key) === CP.eq) {
152
- if (newNode) {
153
- cur.value = newNode.value;
154
- }
155
- //Duplicates are not accepted.
156
- traversing = false;
157
- inserted = cur;
158
- } else if (this._compare(cur.key, newNode.key) === CP.gt) {
159
- // Traverse left of the node
160
- if (cur.left === undefined) {
161
- if (newNode) {
162
- newNode.parent = cur;
163
- }
164
- //Add to the left of the current node
165
- cur.left = newNode;
166
- this._size = this.size + 1;
167
- traversing = false;
168
- inserted = cur.left;
169
- } else {
170
- //Traverse the left of the current node
171
- if (cur.left) cur = cur.left;
172
- }
173
- } else if (this._compare(cur.key, newNode.key) === CP.lt) {
174
- // Traverse right of the node
175
- if (cur.right === undefined) {
176
- if (newNode) {
177
- newNode.parent = cur;
178
- }
179
- //Add to the right of the current node
180
- cur.right = newNode;
181
- this._size = this.size + 1;
182
- traversing = false;
183
- inserted = cur.right;
184
- } else {
185
- //Traverse the left of the current node
186
- if (cur.right) cur = cur.right;
187
- }
188
- }
189
- } else {
190
- traversing = false;
184
+ this._size++;
185
+ return this.root;
186
+ }
187
+
188
+ let current = this.root;
189
+ while (current !== undefined) {
190
+ if (this._compare(current.key, newNode.key) === CP.eq) {
191
+ // if (current !== newNode) {
192
+ // The key value is the same but the reference is different, update the value of the existing node
193
+ this._replaceNode(current, newNode);
194
+ return newNode;
195
+
196
+ // } else {
197
+ // The key value is the same and the reference is the same, replace the entire node
198
+ // this._replaceNode(current, newNode);
199
+
200
+ // return;
201
+ // }
202
+ } else if (this._compare(current.key, newNode.key) === CP.gt) {
203
+ if (current.left === undefined) {
204
+ current.left = newNode;
205
+ newNode.parent = current;
206
+ this._size++;
207
+ return newNode;
208
+ }
209
+ current = current.left;
210
+ } else {
211
+ if (current.right === undefined) {
212
+ current.right = newNode;
213
+ newNode.parent = current;
214
+ this._size++;
215
+ return newNode;
191
216
  }
217
+ current = current.right;
192
218
  }
193
219
  }
194
- return inserted;
220
+
221
+ return undefined;
195
222
  }
196
223
 
197
224
  /**
198
- * Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
199
- * Space Complexity: O(1) - Constant space is used.
225
+ * Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
226
+ * Space Complexity: O(k) - Additional space is required for the sorted array.
200
227
  */
201
228
 
202
229
  /**
203
- * Time Complexity: O(n log n) - Adding each element individually in a balanced tree.
204
- * Space Complexity: O(n) - Additional space is required for the sorted array.
230
+ * Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
231
+ * Space Complexity: O(k) - Additional space is required for the sorted array.
205
232
  *
206
- * The `addMany` function is used to efficiently add multiple keys or nodes with corresponding data
207
- * to a binary search tree.
208
- * @param {(BTNKey | N | undefined)[]} keysOrNodes - An array of keys or nodes to be added to the
209
- * binary search tree. Each element can be of type `BTNKey` (binary tree node key), `N` (binary tree
210
- * node), or `undefined`.
211
- * @param {(V | undefined)[]} [data] - An optional array of values to associate with the keys or
212
- * nodes being added. If provided, the length of the `data` array must be the same as the length of
213
- * the `keysOrNodes` array.
233
+ * The `addMany` function in TypeScript adds multiple nodes to a binary tree, either in a balanced or
234
+ * unbalanced manner, and returns an array of the inserted nodes.
235
+ * @param keysOrNodesOrEntries - An iterable containing keys, nodes, or entries to be added to the
236
+ * binary tree.
214
237
  * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after
215
- * adding the nodes. The default value is `true`.
238
+ * adding the nodes. The default value is true.
216
239
  * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
217
- * type of iteration to use when adding multiple keys or nodes to the binary search tree. It has a
218
- * default value of `this.iterationType`, which means it will use the iteration type specified in the
219
- * current instance of the binary search tree
220
- * @returns The function `addMany` returns an array of nodes (`N`) or `undefined` values.
240
+ * type of iteration to use when adding multiple keys or nodes to the binary tree. It has a default
241
+ * value of `this.iterationType`, which means it will use the iteration type specified by the binary
242
+ * tree instance.
243
+ * @returns The `addMany` function returns an array of `N` or `undefined` values.
221
244
  */
222
245
  override addMany(
223
- keysOrNodes: (BTNKey | N | undefined)[],
224
- data?: (V | undefined)[],
246
+ keysOrNodesOrEntries: Iterable<BTNodeExemplar<V, N>>,
225
247
  isBalanceAdd = true,
226
248
  iterationType = this.iterationType
227
249
  ): (N | undefined)[] {
228
- // TODO this addMany function is inefficient, it should be optimized
229
- function hasNoUndefined(arr: (BTNKey | N | undefined)[]): arr is (BTNKey | N)[] {
230
- return arr.indexOf(undefined) === -1;
250
+ const inserted: (N | undefined)[] = []
251
+ if (!isBalanceAdd) {
252
+ for (const kve of keysOrNodesOrEntries) {
253
+ const nn = this.add(kve)
254
+ inserted.push(nn);
255
+ }
256
+ return inserted;
231
257
  }
258
+ const realBTNExemplars: BTNodePureExemplar<V, N>[] = [];
232
259
 
233
- if (!isBalanceAdd || !hasNoUndefined(keysOrNodes)) {
234
- return super.addMany(keysOrNodes, data).map(n => n ?? undefined);
260
+ const isRealBTNExemplar = (kve: BTNodeExemplar<V, N>): kve is BTNodePureExemplar<V, N> => {
261
+ if (kve === undefined || kve === null) return false;
262
+ return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null));
235
263
  }
236
264
 
237
- const inserted: (N | undefined)[] = [];
238
- const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(
239
- (value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]
240
- );
265
+ for (const kve of keysOrNodesOrEntries) {
266
+ isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
267
+ }
241
268
 
242
- let sorted = [];
269
+ // TODO this addMany function is inefficient, it should be optimized
270
+ let sorted: BTNodePureExemplar<V, N>[] = [];
243
271
 
244
- function _isNodeOrUndefinedTuple(arr: [BTNKey | N, V][]): arr is [N, V][] {
245
- for (const [keyOrNode] of arr) if (keyOrNode instanceof BSTNode) return true;
246
- return false;
247
- }
272
+ sorted = realBTNExemplars.sort((a, b) => {
273
+ let aR: number, bR: number;
274
+ if (this.isEntry(a)) aR = a[0]
275
+ else if (this.isRealNode(a)) aR = a.key
276
+ else aR = a;
248
277
 
249
- const _isBinaryTreeKeyOrNullTuple = (arr: [BTNKey | N, V][]): arr is [BTNKey, V][] => {
250
- for (const [keyOrNode] of arr) if (this.isNodeKey(keyOrNode)) return true;
251
- return false;
252
- };
278
+ if (this.isEntry(b)) bR = b[0]
279
+ else if (this.isRealNode(b)) bR = b.key
280
+ else bR = b;
253
281
 
254
- let sortedKeysOrNodes: (number | N | undefined)[] = [],
255
- sortedData: (V | undefined)[] | undefined = [];
282
+ return aR - bR;
283
+ })
256
284
 
257
- if (_isNodeOrUndefinedTuple(combinedArr)) {
258
- sorted = combinedArr.sort((a, b) => a[0].key - b[0].key);
259
- } else if (_isBinaryTreeKeyOrNullTuple(combinedArr)) {
260
- sorted = combinedArr.sort((a, b) => a[0] - b[0]);
261
- } else {
262
- throw new Error('Invalid input keysOrNodes');
263
- }
264
- sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);
265
- sortedData = sorted.map(([, value]) => value);
266
- const _dfs = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {
285
+
286
+ const _dfs = (arr: BTNodePureExemplar<V, N>[]) => {
267
287
  if (arr.length === 0) return;
268
288
 
269
289
  const mid = Math.floor((arr.length - 1) / 2);
270
- const newNode = this.add(arr[mid], data?.[mid]);
290
+ const newNode = this.add(arr[mid]);
271
291
  inserted.push(newNode);
272
- _dfs(arr.slice(0, mid), data?.slice(0, mid));
273
- _dfs(arr.slice(mid + 1), data?.slice(mid + 1));
292
+ _dfs(arr.slice(0, mid));
293
+ _dfs(arr.slice(mid + 1));
274
294
  };
275
295
  const _iterate = () => {
276
296
  const n = sorted.length;
@@ -281,7 +301,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
281
301
  const [l, r] = popped;
282
302
  if (l <= r) {
283
303
  const m = l + Math.floor((r - l) / 2);
284
- const newNode = this.add(sortedKeysOrNodes[m], sortedData?.[m]);
304
+ const newNode = this.add(sorted[m]);
285
305
  inserted.push(newNode);
286
306
  stack.push([m + 1, r]);
287
307
  stack.push([l, m - 1]);
@@ -290,7 +310,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
290
310
  }
291
311
  };
292
312
  if (iterationType === IterationType.RECURSIVE) {
293
- _dfs(sortedKeysOrNodes, sortedData);
313
+ _dfs(sorted);
294
314
  } else {
295
315
  _iterate();
296
316
  }
@@ -318,7 +338,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
318
338
  * the key of the leftmost node if the comparison result is greater than, and the key of the
319
339
  * rightmost node otherwise. If no node is found, it returns 0.
320
340
  */
321
- lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.iterationType): BTNKey {
341
+ lastKey(beginRoot: BSTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): BTNKey {
322
342
  if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
323
343
  else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
324
344
  else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
@@ -374,7 +394,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
374
394
  */
375
395
 
376
396
  /**
377
- * The function `ensureNotKey` returns the node corresponding to the given key if it is a node key,
397
+ * The function `ensureNode` returns the node corresponding to the given key if it is a node key,
378
398
  * otherwise it returns the key itself.
379
399
  * @param {BTNKey | N | undefined} key - The `key` parameter can be of type `BTNKey`, `N`, or
380
400
  * `undefined`.
@@ -382,7 +402,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
382
402
  * type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`.
383
403
  * @returns either a node object (N) or undefined.
384
404
  */
385
- override ensureNotKey(key: BTNKey | N | undefined, iterationType = IterationType.ITERATIVE): N | undefined {
405
+ override ensureNode(key: BSTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | undefined {
386
406
  return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
387
407
  }
388
408
 
@@ -413,10 +433,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
413
433
  identifier: ReturnType<C> | undefined,
414
434
  callback: C = this._defaultOneParamCallback as C,
415
435
  onlyOne = false,
416
- beginRoot: BTNKey | N | undefined = this.root,
436
+ beginRoot: BSTNodeKeyOrNode<N> = this.root,
417
437
  iterationType = this.iterationType
418
438
  ): N[] {
419
- beginRoot = this.ensureNotKey(beginRoot);
439
+ beginRoot = this.ensureNode(beginRoot);
420
440
  if (!beginRoot) return [];
421
441
  const ans: N[] = [];
422
442
 
@@ -494,10 +514,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
494
514
  lesserOrGreaterTraverse<C extends BTNCallback<N>>(
495
515
  callback: C = this._defaultOneParamCallback as C,
496
516
  lesserOrGreater: CP = CP.lt,
497
- targetNode: BTNKey | N | undefined = this.root,
517
+ targetNode: BSTNodeKeyOrNode<N> = this.root,
498
518
  iterationType = this.iterationType
499
519
  ): ReturnType<C>[] {
500
- targetNode = this.ensureNotKey(targetNode);
520
+ targetNode = this.ensureNode(targetNode);
501
521
  const ans: ReturnType<BTNCallback<N>>[] = [];
502
522
  if (!targetNode) return ans;
503
523
  if (!this.root) return ans;
@@ -559,7 +579,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
559
579
  if (l > r) return;
560
580
  const m = l + Math.floor((r - l) / 2);
561
581
  const midNode = sorted[m];
562
- this.add(midNode.key, midNode.value);
582
+ this.add([midNode.key, midNode.value]);
563
583
  buildBalanceBST(l, m - 1);
564
584
  buildBalanceBST(m + 1, r);
565
585
  };
@@ -576,7 +596,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
576
596
  const m = l + Math.floor((r - l) / 2);
577
597
  const midNode = sorted[m];
578
598
  debugger;
579
- this.add(midNode.key, midNode.value);
599
+ this.add([midNode.key, midNode.value]);
580
600
  stack.push([m + 1, r]);
581
601
  stack.push([l, m - 1]);
582
602
  }
@@ -654,23 +674,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
654
674
  return balanced;
655
675
  }
656
676
 
657
- /**
658
- * Time Complexity: O(n) - Visiting each node once.
659
- * Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
660
- */
661
-
662
- init(elements: IterableEntriesOrKeys<V>): void {
663
- if (elements) {
664
- for (const entryOrKey of elements) {
665
- if (Array.isArray(entryOrKey)) {
666
- const [key, value] = entryOrKey;
667
- this.add(key, value);
668
- } else {
669
- this.add(entryOrKey);
670
- }
671
- }
672
- }
673
- }
674
677
 
675
678
  protected _setRoot(v: N | undefined) {
676
679
  if (v) {
@@ -8,9 +8,10 @@
8
8
 
9
9
  import {
10
10
  BiTreeDeleteResult,
11
+ BSTNodeKeyOrNode,
11
12
  BTNCallback,
12
13
  BTNKey,
13
- IterableEntriesOrKeys,
14
+ BTNodeExemplar,
14
15
  IterationType,
15
16
  RBTNColor,
16
17
  RBTreeOptions,
@@ -45,17 +46,22 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
45
46
  implements IBinaryTree<V, N, TREE> {
46
47
  Sentinel: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
47
48
 
48
-
49
49
  /**
50
- * The constructor function initializes a Red-Black Tree with an optional set of options.
51
- * @param {RBTreeOptions} [options] - The `options` parameter is an optional object that can be
52
- * passed to the constructor. It is used to configure the RBTree object with specific options.
50
+ * This is the constructor function for a Red-Black Tree data structure in TypeScript, which
51
+ * initializes the tree with optional elements and options.
52
+ * @param [elements] - The `elements` parameter is an optional iterable of `BTNodeExemplar<V, N>`
53
+ * objects. It represents the initial elements that will be added to the RBTree during its
54
+ * construction. If this parameter is provided, the `addMany` method is called to add all the
55
+ * elements to the
56
+ * @param [options] - The `options` parameter is an optional object that allows you to customize the
57
+ * behavior of the RBTree. It is of type `Partial<RBTreeOptions>`, which means that you can provide
58
+ * only a subset of the properties defined in the `RBTreeOptions` interface.
53
59
  */
54
- constructor(elements?: IterableEntriesOrKeys<V>, options?: Partial<RBTreeOptions>) {
60
+ constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<RBTreeOptions>) {
55
61
  super([], options);
56
62
 
57
63
  this._root = this.Sentinel;
58
- if (elements) this.init(elements);
64
+ if (elements) super.addMany(elements);
59
65
  }
60
66
 
61
67
  protected _root: N;
@@ -70,10 +76,29 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
70
76
  return this._size;
71
77
  }
72
78
 
79
+ /**
80
+ * The function creates a new Red-Black Tree node with the specified key, value, and color.
81
+ * @param {BTNKey} key - The key parameter is the key value associated with the node. It is used to
82
+ * identify and compare nodes in the Red-Black Tree.
83
+ * @param {V} [value] - The `value` parameter is an optional parameter that represents the value
84
+ * associated with the node. It is of type `V`, which is a generic type that can be replaced with any
85
+ * specific type when using the `createNode` method.
86
+ * @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
87
+ * Red-Black Tree. It can be either "RED" or "BLACK". By default, the color is set to "BLACK".
88
+ * @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
89
+ * value, and color.
90
+ */
73
91
  override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
74
92
  return new RedBlackTreeNode<V, N>(key, value, color) as N;
75
93
  }
76
94
 
95
+ /**
96
+ * The function creates a Red-Black Tree with the specified options and returns it.
97
+ * @param {RBTreeOptions} [options] - The `options` parameter is an optional object that can be
98
+ * passed to the `createTree` function. It is used to customize the behavior of the `RedBlackTree`
99
+ * class.
100
+ * @returns a new instance of a RedBlackTree object.
101
+ */
77
102
  override createTree(options?: RBTreeOptions): TREE {
78
103
  return new RedBlackTree<V, N, TREE>([], {
79
104
  iterationType: this.iterationType,
@@ -84,24 +109,30 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
84
109
  /**
85
110
  * Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
86
111
  * Space Complexity: O(1)
87
- *
88
- * The `add` function adds a new node to a Red-Black Tree data structure.
89
- * @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the
90
- * following types:
91
- * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
92
- * key in the node being added to the Red-Black Tree.
93
- * @returns The method returns either a node (`N`) or `undefined`.
94
112
  */
95
- override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
113
+
114
+
115
+ /**
116
+ * The function adds a node to a Red-Black Tree data structure.
117
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
118
+ * @returns The method `add` returns either an instance of `N` (the node that was added) or
119
+ * `undefined`.
120
+ */
121
+ override add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | undefined {
96
122
  let node: N;
97
- if (this.isNodeKey(keyOrNode)) {
98
- node = this.createNode(keyOrNode, value, RBTNColor.RED);
99
- } else if (keyOrNode instanceof RedBlackTreeNode) {
100
- node = keyOrNode;
101
- } else if (keyOrNode === null) {
102
- return;
103
- } else if (keyOrNode === undefined) {
123
+ if (this.isNodeKey(keyOrNodeOrEntry)) {
124
+ node = this.createNode(keyOrNodeOrEntry, undefined, RBTNColor.RED);
125
+ } else if (keyOrNodeOrEntry instanceof RedBlackTreeNode) {
126
+ node = keyOrNodeOrEntry;
127
+ } else if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) {
104
128
  return;
129
+ } else if (this.isEntry(keyOrNodeOrEntry)) {
130
+ const [key, value] = keyOrNodeOrEntry;
131
+ if (key === undefined || key === null) {
132
+ return;
133
+ } else {
134
+ node = this.createNode(key, value, RBTNColor.RED);
135
+ }
105
136
  } else {
106
137
  return;
107
138
  }
@@ -120,6 +151,9 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
120
151
  } else if (node.key > x.key) {
121
152
  x = x?.right;
122
153
  } else {
154
+ if (node !== x) {
155
+ this._replaceNode(x, node)
156
+ }
123
157
  return;
124
158
  }
125
159
  }
@@ -261,6 +295,11 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
261
295
  iterationType?: IterationType
262
296
  ): N | undefined;
263
297
 
298
+ /**
299
+ * Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
300
+ * Space Complexity: O(1)
301
+ */
302
+
264
303
  /**
265
304
  * Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
266
305
  * Space Complexity: O(1)
@@ -285,11 +324,11 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
285
324
  getNode<C extends BTNCallback<N>>(
286
325
  identifier: ReturnType<C> | undefined,
287
326
  callback: C = this._defaultOneParamCallback as C,
288
- beginRoot: BTNKey | N | undefined = this.root,
327
+ beginRoot: BSTNodeKeyOrNode<N> = this.root,
289
328
  iterationType = this.iterationType
290
329
  ): N | null | undefined {
291
330
  if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
292
- beginRoot = this.ensureNotKey(beginRoot);
331
+ beginRoot = this.ensureNode(beginRoot);
293
332
  return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
294
333
  }
295
334
 
@@ -357,19 +396,6 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
357
396
  this._size = 0;
358
397
  }
359
398
 
360
- init(elements: IterableEntriesOrKeys<V>): void {
361
- if (elements) {
362
- for (const entryOrKey of elements) {
363
- if (Array.isArray(entryOrKey)) {
364
- const [key, value] = entryOrKey;
365
- this.add(key, value);
366
- } else {
367
- this.add(entryOrKey);
368
- }
369
- }
370
- }
371
- }
372
-
373
399
  protected override _setRoot(v: N) {
374
400
  if (v) {
375
401
  v.parent = undefined;
@@ -596,4 +622,19 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
596
622
  }
597
623
  this.root.color = RBTNColor.BLACK;
598
624
  }
625
+
626
+ /**
627
+ * The function replaces an old node with a new node while preserving the color of the old node.
628
+ * @param {N} oldNode - The `oldNode` parameter represents the node that needs to be replaced in a
629
+ * data structure. It is of type `N`, which is the type of the nodes in the data structure.
630
+ * @param {N} newNode - The `newNode` parameter is the node that will replace the `oldNode` in the
631
+ * data structure.
632
+ * @returns The method is returning the result of calling the `_replaceNode` method from the
633
+ * superclass, passing in the `oldNode` and `newNode` as arguments.
634
+ */
635
+ protected _replaceNode(oldNode: N, newNode: N): N {
636
+ newNode.color = oldNode.color;
637
+
638
+ return super._replaceNode(oldNode, newNode)
639
+ }
599
640
  }