graph-typed 1.51.0 → 1.51.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -191,6 +191,16 @@ export class BinaryTree<
191
191
  return this._size;
192
192
  }
193
193
 
194
+ protected _NIL: NODE = new BinaryTreeNode<K, V>(NaN as K) as unknown as NODE;
195
+
196
+ /**
197
+ * The function returns the value of the _NIL property.
198
+ * @returns The method is returning the value of the `_NIL` property.
199
+ */
200
+ get NIL(): NODE {
201
+ return this._NIL;
202
+ }
203
+
194
204
  /**
195
205
  * Creates a new instance of BinaryTreeNode with the given key and value.
196
206
  * @param {K} key - The key for the new node.
@@ -268,17 +278,26 @@ export class BinaryTree<
268
278
  keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
269
279
  iterationType: IterationType = 'ITERATIVE'
270
280
  ): NODE | null | undefined {
271
- let res: NODE | null | undefined;
272
281
  if (this.isRealNode(keyOrNodeOrEntry)) {
273
- res = keyOrNodeOrEntry;
282
+ return keyOrNodeOrEntry;
274
283
  } else if (this.isEntry(keyOrNodeOrEntry)) {
275
- if (keyOrNodeOrEntry[0] === null) res = null;
276
- else if (keyOrNodeOrEntry[0] !== undefined) res = this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
284
+ if (keyOrNodeOrEntry[0] === null) return null;
285
+ if (keyOrNodeOrEntry[0] === undefined) return;
286
+ return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
277
287
  } else {
278
- if (keyOrNodeOrEntry === null) res = null;
279
- else if (keyOrNodeOrEntry !== undefined) res = this.getNodeByKey(keyOrNodeOrEntry, iterationType);
288
+ if (keyOrNodeOrEntry === null) return null;
289
+ if (keyOrNodeOrEntry === undefined) return;
290
+ return this.getNodeByKey(keyOrNodeOrEntry, iterationType);
280
291
  }
281
- return res;
292
+ }
293
+
294
+ /**
295
+ * The function checks if a given node is a real node or null.
296
+ * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
297
+ * @returns a boolean value.
298
+ */
299
+ isNodeOrNull(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
300
+ return this.isRealNode(node) || node === null;
282
301
  }
283
302
 
284
303
  /**
@@ -290,16 +309,6 @@ export class BinaryTree<
290
309
  return keyOrNodeOrEntry instanceof BinaryTreeNode;
291
310
  }
292
311
 
293
- /**
294
- * The function checks if a given value is an entry in a binary tree node.
295
- * @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,NODE> - A generic type representing a node in a binary tree. It has
296
- * two type parameters V and NODE, representing the value and node type respectively.
297
- * @returns a boolean value.
298
- */
299
- isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is BTNEntry<K, V> {
300
- return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
301
- }
302
-
303
312
  /**
304
313
  * The function checks if a given node is a real node by verifying if it is an instance of
305
314
  * BinaryTreeNode and its key is not NaN.
@@ -307,7 +316,8 @@ export class BinaryTree<
307
316
  * @returns a boolean value.
308
317
  */
309
318
  isRealNode(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE {
310
- return node instanceof BinaryTreeNode && String(node.key) !== 'NaN';
319
+ if (!this.isNode(node)) return false;
320
+ return node !== this.NIL;
311
321
  }
312
322
 
313
323
  /**
@@ -316,16 +326,17 @@ export class BinaryTree<
316
326
  * @returns a boolean value.
317
327
  */
318
328
  isNIL(node: KeyOrNodeOrEntry<K, V, NODE>) {
319
- return node instanceof BinaryTreeNode && String(node.key) === 'NaN';
329
+ return node === this.NIL;
320
330
  }
321
331
 
322
332
  /**
323
- * The function checks if a given node is a real node or null.
324
- * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
333
+ * The function checks if a given value is an entry in a binary tree node.
334
+ * @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,NODE> - A generic type representing a node in a binary tree. It has
335
+ * two type parameters V and NODE, representing the value and node type respectively.
325
336
  * @returns a boolean value.
326
337
  */
327
- isNodeOrNull(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
328
- return this.isRealNode(node) || node === null;
338
+ isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is BTNEntry<K, V> {
339
+ return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
329
340
  }
330
341
 
331
342
  /**
@@ -486,16 +497,16 @@ export class BinaryTree<
486
497
  * specific node based on its value or object.
487
498
  * @param {C} callback - The `callback` parameter is a function that is used to determine the
488
499
  * identifier of the node to be deleted. It is optional and has a default value of
489
- * `this._defaultOneParamCallback`. The `callback` function should return the identifier of the node.
500
+ * `this._DEFAULT_CALLBACK`. The `callback` function should return the identifier of the node.
490
501
  * @returns an array of `BinaryTreeDeleteResult<NODE>`.
491
502
  */
492
503
  delete<C extends BTNCallback<NODE>>(
493
504
  identifier: ReturnType<C> | null | undefined,
494
- callback: C = this._defaultOneParamCallback as C
505
+ callback: C = this._DEFAULT_CALLBACK as C
495
506
  ): BinaryTreeDeleteResult<NODE>[] {
496
507
  const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
497
508
  if (!this.root) return deletedResult;
498
- if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
509
+ if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
499
510
  callback = (node => node) as C;
500
511
 
501
512
  const curr = this.getNode(identifier, callback);
@@ -579,7 +590,7 @@ export class BinaryTree<
579
590
  * specific value.
580
591
  * @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as
581
592
  * input and returns a value of type `C`. It is used to determine if a node matches the given
582
- * identifier. If no callback is provided, the `_defaultOneParamCallback` function is used as the
593
+ * identifier. If no callback is provided, the `_DEFAULT_CALLBACK` function is used as the
583
594
  * default
584
595
  * @param [onlyOne=false] - A boolean value indicating whether to only return the first node that
585
596
  * matches the identifier. If set to true, the function will stop iterating once it finds a matching
@@ -594,12 +605,12 @@ export class BinaryTree<
594
605
  */
595
606
  getNodes<C extends BTNCallback<NODE>>(
596
607
  identifier: ReturnType<C> | null | undefined,
597
- callback: C = this._defaultOneParamCallback as C,
608
+ callback: C = this._DEFAULT_CALLBACK as C,
598
609
  onlyOne = false,
599
610
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
600
611
  iterationType: IterationType = this.iterationType
601
612
  ): NODE[] {
602
- if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
613
+ if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
603
614
  callback = (node => node) as C;
604
615
  beginRoot = this.ensureNode(beginRoot);
605
616
  if (!beginRoot) return [];
@@ -607,28 +618,28 @@ export class BinaryTree<
607
618
  const ans: NODE[] = [];
608
619
 
609
620
  if (iterationType === 'RECURSIVE') {
610
- const _traverse = (cur: NODE) => {
621
+ const dfs = (cur: NODE) => {
611
622
  if (callback(cur) === identifier) {
612
623
  ans.push(cur);
613
624
  if (onlyOne) return;
614
625
  }
615
- if (!cur.left && !cur.right) return;
616
- cur.left && _traverse(cur.left);
617
- cur.right && _traverse(cur.right);
626
+ if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
627
+ this.isRealNode(cur.left) && dfs(cur.left);
628
+ this.isRealNode(cur.right) && dfs(cur.right);
618
629
  };
619
630
 
620
- _traverse(beginRoot);
631
+ dfs(beginRoot);
621
632
  } else {
622
- const queue = new Queue<NODE>([beginRoot]);
623
- while (queue.size > 0) {
624
- const cur = queue.shift();
625
- if (cur) {
633
+ const stack = [beginRoot];
634
+ while (stack.length > 0) {
635
+ const cur = stack.pop();
636
+ if (this.isRealNode(cur)) {
626
637
  if (callback(cur) === identifier) {
627
638
  ans.push(cur);
628
639
  if (onlyOne) return ans;
629
640
  }
630
- cur.left && queue.push(cur.left);
631
- cur.right && queue.push(cur.right);
641
+ this.isRealNode(cur.left) && stack.push(cur.left);
642
+ this.isRealNode(cur.right) && stack.push(cur.right);
632
643
  }
633
644
  }
634
645
  }
@@ -685,13 +696,10 @@ export class BinaryTree<
685
696
  */
686
697
  getNode<C extends BTNCallback<NODE>>(
687
698
  identifier: ReturnType<C> | null | undefined,
688
- callback: C = this._defaultOneParamCallback as C,
699
+ callback: C = this._DEFAULT_CALLBACK as C,
689
700
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
690
701
  iterationType: IterationType = this.iterationType
691
702
  ): NODE | null | undefined {
692
- if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
693
- callback = (node => node) as C;
694
-
695
703
  return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
696
704
  }
697
705
 
@@ -717,23 +725,23 @@ export class BinaryTree<
717
725
  getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
718
726
  if (!this.root) return undefined;
719
727
  if (iterationType === 'RECURSIVE') {
720
- const _dfs = (cur: NODE): NODE | undefined => {
728
+ const dfs = (cur: NODE): NODE | undefined => {
721
729
  if (cur.key === key) return cur;
722
730
 
723
731
  if (!cur.left && !cur.right) return;
724
- if (cur.left) return _dfs(cur.left);
725
- if (cur.right) return _dfs(cur.right);
732
+ if (cur.left) return dfs(cur.left);
733
+ if (cur.right) return dfs(cur.right);
726
734
  };
727
735
 
728
- return _dfs(this.root);
736
+ return dfs(this.root);
729
737
  } else {
730
- const queue = new Queue<NODE>([this.root]);
731
- while (queue.size > 0) {
732
- const cur = queue.shift();
738
+ const stack = [this.root];
739
+ while (stack.length > 0) {
740
+ const cur = stack.pop();
733
741
  if (cur) {
734
742
  if (cur.key === key) return cur;
735
- cur.left && queue.push(cur.left);
736
- cur.right && queue.push(cur.right);
743
+ cur.left && stack.push(cur.left);
744
+ cur.right && stack.push(cur.right);
737
745
  }
738
746
  }
739
747
  }
@@ -789,13 +797,10 @@ export class BinaryTree<
789
797
  */
790
798
  override get<C extends BTNCallback<NODE>>(
791
799
  identifier: ReturnType<C> | null | undefined,
792
- callback: C = this._defaultOneParamCallback as C,
800
+ callback: C = this._DEFAULT_CALLBACK as C,
793
801
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
794
802
  iterationType: IterationType = this.iterationType
795
803
  ): V | undefined {
796
- if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
797
- callback = (node => node) as C;
798
-
799
804
  return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
800
805
  }
801
806
 
@@ -848,11 +853,11 @@ export class BinaryTree<
848
853
  */
849
854
  override has<C extends BTNCallback<NODE>>(
850
855
  identifier: ReturnType<C> | null | undefined,
851
- callback: C = this._defaultOneParamCallback as C,
856
+ callback: C = this._DEFAULT_CALLBACK as C,
852
857
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
853
858
  iterationType: IterationType = this.iterationType
854
859
  ): boolean {
855
- if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
860
+ if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
856
861
  callback = (node => node) as C;
857
862
 
858
863
  return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
@@ -1184,20 +1189,20 @@ export class BinaryTree<
1184
1189
  if (!this.isRealNode(beginRoot)) return beginRoot;
1185
1190
 
1186
1191
  if (iterationType === 'RECURSIVE') {
1187
- const _traverse = (cur: NODE): NODE => {
1192
+ const dfs = (cur: NODE): NODE => {
1188
1193
  if (!this.isRealNode(cur.left)) return cur;
1189
- return _traverse(cur.left);
1194
+ return dfs(cur.left);
1190
1195
  };
1191
1196
 
1192
- return _traverse(beginRoot);
1197
+ return dfs(beginRoot);
1193
1198
  } else {
1194
1199
  // Indirect implementation of iteration using tail recursion optimization
1195
- const _traverse = trampoline((cur: NODE) => {
1200
+ const dfs = trampoline((cur: NODE) => {
1196
1201
  if (!this.isRealNode(cur.left)) return cur;
1197
- return _traverse.cont(cur.left);
1202
+ return dfs.cont(cur.left);
1198
1203
  });
1199
1204
 
1200
- return _traverse(beginRoot);
1205
+ return dfs(beginRoot);
1201
1206
  }
1202
1207
  }
1203
1208
 
@@ -1231,20 +1236,20 @@ export class BinaryTree<
1231
1236
  if (!beginRoot) return beginRoot;
1232
1237
 
1233
1238
  if (iterationType === 'RECURSIVE') {
1234
- const _traverse = (cur: NODE): NODE => {
1239
+ const dfs = (cur: NODE): NODE => {
1235
1240
  if (!this.isRealNode(cur.right)) return cur;
1236
- return _traverse(cur.right);
1241
+ return dfs(cur.right);
1237
1242
  };
1238
1243
 
1239
- return _traverse(beginRoot);
1244
+ return dfs(beginRoot);
1240
1245
  } else {
1241
1246
  // Indirect implementation of iteration using tail recursion optimization
1242
- const _traverse = trampoline((cur: NODE) => {
1247
+ const dfs = trampoline((cur: NODE) => {
1243
1248
  if (!this.isRealNode(cur.right)) return cur;
1244
- return _traverse.cont(cur.right);
1249
+ return dfs.cont(cur.right);
1245
1250
  });
1246
1251
 
1247
- return _traverse(beginRoot);
1252
+ return dfs(beginRoot);
1248
1253
  }
1249
1254
  }
1250
1255
 
@@ -1351,7 +1356,7 @@ export class BinaryTree<
1351
1356
  * @returns an array of values that are the return values of the callback function.
1352
1357
  */
1353
1358
  dfs<C extends BTNCallback<NODE | null | undefined>>(
1354
- callback: C = this._defaultOneParamCallback as C,
1359
+ callback: C = this._DEFAULT_CALLBACK as C,
1355
1360
  pattern: DFSOrderPattern = 'IN',
1356
1361
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
1357
1362
  iterationType: IterationType = 'ITERATIVE',
@@ -1361,38 +1366,38 @@ export class BinaryTree<
1361
1366
  if (!beginRoot) return [];
1362
1367
  const ans: ReturnType<C>[] = [];
1363
1368
  if (iterationType === 'RECURSIVE') {
1364
- const _traverse = (node: NODE | null | undefined) => {
1369
+ const dfs = (node: NODE | null | undefined) => {
1365
1370
  switch (pattern) {
1366
1371
  case 'IN':
1367
1372
  if (includeNull) {
1368
- if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
1373
+ if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
1369
1374
  this.isNodeOrNull(node) && ans.push(callback(node));
1370
- if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right);
1375
+ if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
1371
1376
  } else {
1372
- if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left);
1377
+ if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
1373
1378
  this.isRealNode(node) && ans.push(callback(node));
1374
- if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
1379
+ if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
1375
1380
  }
1376
1381
  break;
1377
1382
  case 'PRE':
1378
1383
  if (includeNull) {
1379
1384
  this.isNodeOrNull(node) && ans.push(callback(node));
1380
- if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
1381
- if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right);
1385
+ if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
1386
+ if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
1382
1387
  } else {
1383
1388
  this.isRealNode(node) && ans.push(callback(node));
1384
- if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left);
1385
- if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
1389
+ if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
1390
+ if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
1386
1391
  }
1387
1392
  break;
1388
1393
  case 'POST':
1389
1394
  if (includeNull) {
1390
- if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
1391
- if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right);
1395
+ if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
1396
+ if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
1392
1397
  this.isNodeOrNull(node) && ans.push(callback(node));
1393
1398
  } else {
1394
- if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left);
1395
- if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
1399
+ if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
1400
+ if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
1396
1401
  this.isRealNode(node) && ans.push(callback(node));
1397
1402
  }
1398
1403
 
@@ -1400,7 +1405,7 @@ export class BinaryTree<
1400
1405
  }
1401
1406
  };
1402
1407
 
1403
- _traverse(beginRoot);
1408
+ dfs(beginRoot);
1404
1409
  } else {
1405
1410
  // 0: visit, 1: print
1406
1411
  const stack: { opt: 0 | 1; node: NODE | null | undefined }[] = [{ opt: 0, node: beginRoot }];
@@ -1486,7 +1491,7 @@ export class BinaryTree<
1486
1491
  * the breadth-first traversal of a binary tree.
1487
1492
  */
1488
1493
  bfs<C extends BTNCallback<NODE | null>>(
1489
- callback: C = this._defaultOneParamCallback as C,
1494
+ callback: C = this._DEFAULT_CALLBACK as C,
1490
1495
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
1491
1496
  iterationType: IterationType = this.iterationType,
1492
1497
  includeNull = false
@@ -1499,7 +1504,7 @@ export class BinaryTree<
1499
1504
  if (iterationType === 'RECURSIVE') {
1500
1505
  const queue: Queue<NODE | null | undefined> = new Queue<NODE | null | undefined>([beginRoot]);
1501
1506
 
1502
- const traverse = (level: number) => {
1507
+ const dfs = (level: number) => {
1503
1508
  if (queue.size === 0) return;
1504
1509
 
1505
1510
  const current = queue.shift()!;
@@ -1513,10 +1518,10 @@ export class BinaryTree<
1513
1518
  if (this.isRealNode(current.right)) queue.push(current.right);
1514
1519
  }
1515
1520
 
1516
- traverse(level + 1);
1521
+ dfs(level + 1);
1517
1522
  };
1518
1523
 
1519
- traverse(0);
1524
+ dfs(0);
1520
1525
  } else {
1521
1526
  const queue = new Queue<NODE | null | undefined>([beginRoot]);
1522
1527
  while (queue.size > 0) {
@@ -1580,7 +1585,7 @@ export class BinaryTree<
1580
1585
  * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
1581
1586
  */
1582
1587
  listLevels<C extends BTNCallback<NODE | null>>(
1583
- callback: C = this._defaultOneParamCallback as C,
1588
+ callback: C = this._DEFAULT_CALLBACK as C,
1584
1589
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
1585
1590
  iterationType: IterationType = this.iterationType,
1586
1591
  includeNull = false
@@ -1651,7 +1656,7 @@ export class BinaryTree<
1651
1656
  * by the return type of the `callback` function.
1652
1657
  */
1653
1658
  morris<C extends BTNCallback<NODE>>(
1654
- callback: C = this._defaultOneParamCallback as C,
1659
+ callback: C = this._DEFAULT_CALLBACK as C,
1655
1660
  pattern: DFSOrderPattern = 'IN',
1656
1661
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root
1657
1662
  ): ReturnType<C>[] {
@@ -1995,7 +2000,7 @@ export class BinaryTree<
1995
2000
  }
1996
2001
  }
1997
2002
 
1998
- protected _defaultOneParamCallback = (node: NODE | null | undefined) => (node ? node.key : undefined);
2003
+ protected _DEFAULT_CALLBACK = (node: NODE | null | undefined) => (node ? node.key : undefined);
1999
2004
 
2000
2005
  /**
2001
2006
  * Swap the data of two nodes in the binary tree.
@@ -13,7 +13,7 @@ import type {
13
13
  BTNodePureExemplar,
14
14
  KeyOrNodeOrEntry
15
15
  } from '../../types';
16
- import { BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
16
+ import { BSTNKeyOrNode, BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
17
17
  import { BinaryTree, BinaryTreeNode } from './binary-tree';
18
18
  import { IBinaryTree } from '../../interfaces';
19
19
  import { Queue } from '../queue';
@@ -214,15 +214,15 @@ export class BST<
214
214
  keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
215
215
  iterationType: IterationType = 'ITERATIVE'
216
216
  ): NODE | undefined {
217
- let res: NODE | undefined;
218
217
  if (this.isRealNode(keyOrNodeOrEntry)) {
219
- res = keyOrNodeOrEntry;
218
+ return keyOrNodeOrEntry;
220
219
  } else if (this.isEntry(keyOrNodeOrEntry)) {
221
- if (keyOrNodeOrEntry[0]) res = this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
220
+ if (keyOrNodeOrEntry[0] === null || keyOrNodeOrEntry[0] === undefined) return;
221
+ return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
222
222
  } else {
223
- if (keyOrNodeOrEntry) res = this.getNodeByKey(keyOrNodeOrEntry, iterationType);
223
+ if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) return;
224
+ return this.getNodeByKey(keyOrNodeOrEntry, iterationType);
224
225
  }
225
- return res;
226
226
  }
227
227
 
228
228
  /**
@@ -426,26 +426,26 @@ export class BST<
426
426
  * found in the binary tree. If no node is found, it returns `undefined`.
427
427
  */
428
428
  override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
429
- // return this.getNodes(key, this._defaultOneParamCallback, true, this.root, iterationType)[0];
430
- if (!this.isRealNode(this.root)) return undefined;
429
+ // return this.getNodes(key, this._DEFAULT_CALLBACK, true, this.root, iterationType)[0];
430
+ if (!this.isRealNode(this.root)) return;
431
431
  if (iterationType === 'RECURSIVE') {
432
- const _dfs = (cur: NODE): NODE | undefined => {
432
+ const dfs = (cur: NODE): NODE | undefined => {
433
433
  if (cur.key === key) return cur;
434
434
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
435
435
 
436
- if (this._compare(cur.key, key) === 'GT' && this.isRealNode(cur.left)) return _dfs(cur.left);
437
- if (this._compare(cur.key, key) === 'LT' && this.isRealNode(cur.right)) return _dfs(cur.right);
436
+ if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') return dfs(cur.left);
437
+ if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') return dfs(cur.right);
438
438
  };
439
439
 
440
- return _dfs(this.root);
440
+ return dfs(this.root);
441
441
  } else {
442
- const queue = new Queue<NODE>([this.root]);
443
- while (queue.size > 0) {
444
- const cur = queue.shift();
442
+ const stack = [this.root];
443
+ while (stack.length > 0) {
444
+ const cur = stack.pop();
445
445
  if (this.isRealNode(cur)) {
446
446
  if (this._compare(cur.key, key) === 'EQ') return cur;
447
- if (this._compare(cur.key, key) === 'GT') this.isRealNode(cur.left) && queue.push(cur.left);
448
- if (this._compare(cur.key, key) === 'LT') this.isRealNode(cur.right) && queue.push(cur.right);
447
+ if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') stack.push(cur.left);
448
+ if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') stack.push(cur.right);
449
449
  }
450
450
  }
451
451
  }
@@ -481,7 +481,7 @@ export class BST<
481
481
  */
482
482
  override getNodes<C extends BTNCallback<NODE>>(
483
483
  identifier: ReturnType<C> | undefined,
484
- callback: C = this._defaultOneParamCallback as C,
484
+ callback: C = this._DEFAULT_CALLBACK as C,
485
485
  onlyOne = false,
486
486
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
487
487
  iterationType: IterationType = this.iterationType
@@ -491,7 +491,7 @@ export class BST<
491
491
  const ans: NODE[] = [];
492
492
 
493
493
  if (iterationType === 'RECURSIVE') {
494
- const _traverse = (cur: NODE) => {
494
+ const dfs = (cur: NODE) => {
495
495
  const callbackResult = callback(cur);
496
496
  if (callbackResult === identifier) {
497
497
  ans.push(cur);
@@ -500,16 +500,16 @@ export class BST<
500
500
 
501
501
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
502
502
  // TODO potential bug
503
- if (callback === this._defaultOneParamCallback) {
504
- if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') _traverse(cur.left);
505
- if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') _traverse(cur.right);
503
+ if (callback === this._DEFAULT_CALLBACK) {
504
+ if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') dfs(cur.left);
505
+ if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') dfs(cur.right);
506
506
  } else {
507
- this.isRealNode(cur.left) && _traverse(cur.left);
508
- this.isRealNode(cur.right) && _traverse(cur.right);
507
+ this.isRealNode(cur.left) && dfs(cur.left);
508
+ this.isRealNode(cur.right) && dfs(cur.right);
509
509
  }
510
510
  };
511
511
 
512
- _traverse(beginRoot);
512
+ dfs(beginRoot);
513
513
  } else {
514
514
  const stack = [beginRoot];
515
515
  while (stack.length > 0) {
@@ -521,7 +521,7 @@ export class BST<
521
521
  if (onlyOne) return ans;
522
522
  }
523
523
  // TODO potential bug
524
- if (callback === this._defaultOneParamCallback) {
524
+ if (callback === this._DEFAULT_CALLBACK) {
525
525
  if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right);
526
526
  if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left);
527
527
 
@@ -543,6 +543,41 @@ export class BST<
543
543
  return ans;
544
544
  }
545
545
 
546
+ /**
547
+ * Time Complexity: O(log n)
548
+ * Space Complexity: O(1)
549
+ */
550
+
551
+ /**
552
+ * Time Complexity: O(log n)
553
+ * Space Complexity: O(1)
554
+ *
555
+ * The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and
556
+ * callback function.
557
+ * @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value or key
558
+ * that you want to search for in the binary search tree. It can be of any type that is compatible
559
+ * with the type of nodes in the tree.
560
+ * @param {C} callback - The `callback` parameter is a function that will be called for each node in
561
+ * the tree. It is used to determine whether a node matches the given identifier. The `callback`
562
+ * function should take a node as its parameter and return a value that can be compared to the
563
+ * `identifier` parameter.
564
+ * @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
565
+ * search tree. It can be either a key or a node. If it is a key, it will be converted to a node
566
+ * using the `ensureNode` method. If it is not provided, the `root`
567
+ * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
568
+ * be performed when searching for nodes in the binary search tree. It is an optional parameter and
569
+ * its default value is taken from the `iterationType` property of the class.
570
+ * @returns The method is returning a value of type `NODE | null | undefined`.
571
+ */
572
+ override getNode<C extends BTNCallback<NODE>>(
573
+ identifier: ReturnType<C> | undefined,
574
+ callback: C = this._DEFAULT_CALLBACK as C,
575
+ beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
576
+ iterationType: IterationType = this.iterationType
577
+ ): NODE | undefined {
578
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
579
+ }
580
+
546
581
  /**
547
582
  * Time complexity: O(n)
548
583
  * Space complexity: O(n)
@@ -568,7 +603,7 @@ export class BST<
568
603
  * @returns The method is returning an array of the return type of the callback function.
569
604
  */
570
605
  override dfs<C extends BTNCallback<NODE>>(
571
- callback: C = this._defaultOneParamCallback as C,
606
+ callback: C = this._DEFAULT_CALLBACK as C,
572
607
  pattern: DFSOrderPattern = 'IN',
573
608
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
574
609
  iterationType: IterationType = 'ITERATIVE'
@@ -599,7 +634,7 @@ export class BST<
599
634
  * @returns The method is returning an array of the return type of the callback function.
600
635
  */
601
636
  override bfs<C extends BTNCallback<NODE>>(
602
- callback: C = this._defaultOneParamCallback as C,
637
+ callback: C = this._DEFAULT_CALLBACK as C,
603
638
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
604
639
  iterationType: IterationType = this.iterationType
605
640
  ): ReturnType<C>[] {
@@ -630,7 +665,7 @@ export class BST<
630
665
  * function.
631
666
  */
632
667
  override listLevels<C extends BTNCallback<NODE>>(
633
- callback: C = this._defaultOneParamCallback as C,
668
+ callback: C = this._DEFAULT_CALLBACK as C,
634
669
  beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
635
670
  iterationType: IterationType = this.iterationType
636
671
  ): ReturnType<C>[][] {
@@ -700,7 +735,7 @@ export class BST<
700
735
  * `ReturnType<C>`, which is the return type of the callback function passed as an argument.
701
736
  */
702
737
  lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
703
- callback: C = this._defaultOneParamCallback as C,
738
+ callback: C = this._DEFAULT_CALLBACK as C,
704
739
  lesserOrGreater: CP = 'LT',
705
740
  targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
706
741
  iterationType: IterationType = this.iterationType
@@ -713,15 +748,15 @@ export class BST<
713
748
  const targetKey = targetNode.key;
714
749
 
715
750
  if (iterationType === 'RECURSIVE') {
716
- const _traverse = (cur: NODE) => {
751
+ const dfs = (cur: NODE) => {
717
752
  const compared = this._compare(cur.key, targetKey);
718
753
  if (compared === lesserOrGreater) ans.push(callback(cur));
719
754
 
720
- if (this.isRealNode(cur.left)) _traverse(cur.left);
721
- if (this.isRealNode(cur.right)) _traverse(cur.right);
755
+ if (this.isRealNode(cur.left)) dfs(cur.left);
756
+ if (this.isRealNode(cur.right)) dfs(cur.right);
722
757
  };
723
758
 
724
- _traverse(this.root);
759
+ dfs(this.root);
725
760
  return ans;
726
761
  } else {
727
762
  const queue = new Queue<NODE>([this.root]);