binary-tree-typed 2.4.4 → 2.5.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 (85) hide show
  1. package/README.md +0 -84
  2. package/dist/cjs/index.cjs +965 -420
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +962 -417
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +965 -421
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +962 -418
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/common/error.d.ts +23 -0
  11. package/dist/types/common/index.d.ts +1 -0
  12. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  13. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  14. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  15. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  16. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  17. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  18. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  19. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  20. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  21. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  22. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  23. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  24. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  25. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  26. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  27. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  28. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  29. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  30. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  31. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  32. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  33. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  34. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  35. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  36. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  37. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  38. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  39. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  40. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  41. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  42. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  43. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  44. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  45. package/dist/umd/binary-tree-typed.js +959 -414
  46. package/dist/umd/binary-tree-typed.js.map +1 -1
  47. package/dist/umd/binary-tree-typed.min.js +3 -3
  48. package/dist/umd/binary-tree-typed.min.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/common/error.ts +60 -0
  51. package/src/common/index.ts +2 -0
  52. package/src/data-structures/base/iterable-element-base.ts +2 -2
  53. package/src/data-structures/binary-tree/avl-tree.ts +134 -51
  54. package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
  55. package/src/data-structures/binary-tree/binary-tree.ts +542 -121
  56. package/src/data-structures/binary-tree/bst.ts +346 -37
  57. package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
  58. package/src/data-structures/binary-tree/segment-tree.ts +372 -248
  59. package/src/data-structures/binary-tree/tree-map.ts +1292 -13
  60. package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
  61. package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
  62. package/src/data-structures/binary-tree/tree-set.ts +1143 -15
  63. package/src/data-structures/graph/abstract-graph.ts +106 -1
  64. package/src/data-structures/graph/directed-graph.ts +223 -47
  65. package/src/data-structures/graph/map-graph.ts +59 -1
  66. package/src/data-structures/graph/undirected-graph.ts +299 -59
  67. package/src/data-structures/hash/hash-map.ts +243 -79
  68. package/src/data-structures/heap/heap.ts +291 -102
  69. package/src/data-structures/heap/max-heap.ts +48 -3
  70. package/src/data-structures/heap/min-heap.ts +59 -0
  71. package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
  72. package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
  73. package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
  74. package/src/data-structures/matrix/matrix.ts +425 -22
  75. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  76. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  77. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  78. package/src/data-structures/queue/deque.ts +343 -68
  79. package/src/data-structures/queue/queue.ts +211 -42
  80. package/src/data-structures/stack/stack.ts +174 -32
  81. package/src/data-structures/trie/trie.ts +215 -44
  82. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  83. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  84. package/src/types/data-structures/queue/deque.ts +7 -0
  85. package/src/utils/utils.ts +4 -2
@@ -28,7 +28,7 @@ import { IBinaryTree } from '../../interfaces';
28
28
  import { isComparable, makeTrampoline, makeTrampolineThunk } from '../../utils';
29
29
  import { Queue } from '../queue';
30
30
  import { IterableEntryBase } from '../base';
31
- import { DFSOperation, Range } from '../../common';
31
+ import { DFSOperation, ERR, Range } from '../../common';
32
32
 
33
33
  /**
34
34
  * @template K - The type of the key.
@@ -205,84 +205,6 @@ export class BinaryTreeNode<K = any, V = any> {
205
205
  * 5. Leaf Nodes: Nodes without children are leaves.
206
206
  *
207
207
  * @example
208
- * // basic BinaryTree creation and insertion
209
- * // Create a BinaryTree with entries
210
- * const entries: [number, string][] = [
211
- * [6, 'six'],
212
- * [1, 'one'],
213
- * [2, 'two'],
214
- * [7, 'seven'],
215
- * [5, 'five'],
216
- * [3, 'three'],
217
- * [4, 'four'],
218
- * [9, 'nine'],
219
- * [8, 'eight']
220
- * ];
221
- *
222
- * const tree = new BinaryTree(entries);
223
- *
224
- * // Verify size
225
- * console.log(tree.size); // 9;
226
- *
227
- * // Add new element
228
- * tree.set(10, 'ten');
229
- * console.log(tree.size); // 10;
230
- * @example
231
- * // BinaryTree get and has operations
232
- * const tree = new BinaryTree(
233
- * [
234
- * [5, 'five'],
235
- * [3, 'three'],
236
- * [7, 'seven'],
237
- * [1, 'one'],
238
- * [4, 'four'],
239
- * [6, 'six'],
240
- * [8, 'eight']
241
- * ],
242
- * { isMapMode: false }
243
- * );
244
- *
245
- * // Check if key exists
246
- * console.log(tree.has(5)); // true;
247
- * console.log(tree.has(10)); // false;
248
- *
249
- * // Get value by key
250
- * console.log(tree.get(3)); // 'three';
251
- * console.log(tree.get(7)); // 'seven';
252
- * console.log(tree.get(100)); // undefined;
253
- *
254
- * // Get node structure
255
- * const node = tree.getNode(5);
256
- * console.log(node?.key); // 5;
257
- * console.log(node?.value); // 'five';
258
- * @example
259
- * // BinaryTree level-order traversal
260
- * const tree = new BinaryTree([
261
- * [1, 'one'],
262
- * [2, 'two'],
263
- * [3, 'three'],
264
- * [4, 'four'],
265
- * [5, 'five'],
266
- * [6, 'six'],
267
- * [7, 'seven']
268
- * ]);
269
- *
270
- * // Binary tree maintains level-order insertion
271
- * // Complete binary tree structure
272
- * console.log(tree.size); // 7;
273
- *
274
- * // Verify all keys are present
275
- * console.log(tree.has(1)); // true;
276
- * console.log(tree.has(4)); // true;
277
- * console.log(tree.has(7)); // true;
278
- *
279
- * // Iterate through tree
280
- * const keys: number[] = [];
281
- * for (const [key] of tree) {
282
- * keys.push(key);
283
- * }
284
- * console.log(keys.length); // 7;
285
- * @example
286
208
  * // determine loan approval using a decision tree
287
209
  * // Decision tree structure
288
210
  * const loanDecisionTree = new BinaryTree<string>(
@@ -371,7 +293,7 @@ export class BinaryTree<K = any, V = any, R = any>
371
293
  if (isMapMode !== undefined) this._isMapMode = isMapMode;
372
294
  if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;
373
295
  if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;
374
- else if (toEntryFn) throw TypeError('toEntryFn must be a function type');
296
+ else if (toEntryFn) throw new TypeError(ERR.notAFunction('toEntryFn', 'BinaryTree'));
375
297
  }
376
298
 
377
299
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
@@ -644,6 +566,20 @@ export class BinaryTree<K = any, V = any, R = any>
644
566
  *
645
567
  * @param keyNodeOrEntry - The key, node, or entry to add.
646
568
  * @returns True if the addition was successful, false otherwise.
569
+
570
+
571
+
572
+
573
+
574
+
575
+ * @example
576
+ * // Add a single node
577
+ * const tree = new BinaryTree<number>();
578
+ * tree.add(1);
579
+ * tree.add(2);
580
+ * tree.add(3);
581
+ * console.log(tree.size); // 3;
582
+ * console.log(tree.has(1)); // true;
647
583
  */
648
584
  add(
649
585
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -658,6 +594,40 @@ export class BinaryTree<K = any, V = any, R = any>
658
594
  * @param keyNodeOrEntry - The key, node, or entry to set or update.
659
595
  * @param [value] - The value, if providing just a key.
660
596
  * @returns True if the addition was successful, false otherwise.
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+ * @example
609
+ * // basic BinaryTree creation and insertion
610
+ * // Create a BinaryTree with entries
611
+ * const entries: [number, string][] = [
612
+ * [6, 'six'],
613
+ * [1, 'one'],
614
+ * [2, 'two'],
615
+ * [7, 'seven'],
616
+ * [5, 'five'],
617
+ * [3, 'three'],
618
+ * [4, 'four'],
619
+ * [9, 'nine'],
620
+ * [8, 'eight']
621
+ * ];
622
+ *
623
+ * const tree = new BinaryTree(entries);
624
+ *
625
+ * // Verify size
626
+ * console.log(tree.size); // 9;
627
+ *
628
+ * // Add new element
629
+ * tree.set(10, 'ten');
630
+ * console.log(tree.size); // 10;
661
631
  */
662
632
  set(
663
633
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -670,7 +640,7 @@ export class BinaryTree<K = any, V = any, R = any>
670
640
  if (!this._root) {
671
641
  this._setRoot(newNode);
672
642
  if (this._isMapMode && newNode !== null && newNode !== undefined) this._store.set(newNode.key, newNode);
673
- this._size = 1;
643
+ if (newNode !== null) this._size = 1;
674
644
  return true;
675
645
  }
676
646
 
@@ -708,7 +678,7 @@ export class BinaryTree<K = any, V = any, R = any>
708
678
  potentialParent.right = newNode;
709
679
  }
710
680
  if (this._isMapMode && newNode !== null && newNode !== undefined) this._store.set(newNode.key, newNode);
711
- this._size++;
681
+ if (newNode !== null) this._size++;
712
682
  return true;
713
683
  }
714
684
 
@@ -721,6 +691,20 @@ export class BinaryTree<K = any, V = any, R = any>
721
691
  *
722
692
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
723
693
  * @returns An array of booleans indicating the success of each individual `set` operation.
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+ * @example
704
+ * // Bulk add
705
+ * const tree = new BinaryTree<number>();
706
+ * tree.addMany([1, 2, 3, 4, 5]);
707
+ * console.log(tree.size); // 5;
724
708
  */
725
709
  addMany(
726
710
  keysNodesEntriesOrRaws: Iterable<
@@ -737,6 +721,13 @@ export class BinaryTree<K = any, V = any, R = any>
737
721
  * @param keysNodesEntriesOrRaws - An iterable of items to set or update.
738
722
  * @param [values] - An optional parallel iterable of values.
739
723
  * @returns An array of booleans indicating the success of each individual `set` operation.
724
+
725
+
726
+ * @example
727
+ * // Set multiple entries
728
+ * const tree = new BinaryTree<number, string>();
729
+ * tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
730
+ * console.log(tree.size); // 3;
740
731
  */
741
732
  setMany(
742
733
  keysNodesEntriesOrRaws: Iterable<
@@ -772,6 +763,21 @@ export class BinaryTree<K = any, V = any, R = any>
772
763
  * @remarks Time O(N * M), same as `setMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `set`).
773
764
  *
774
765
  * @param anotherTree - The tree to merge.
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+ * @example
776
+ * // Combine trees
777
+ * const t1 = new BinaryTree<number>([1, 2]);
778
+ * const t2 = new BinaryTree<number>([3, 4]);
779
+ * t1.merge(t2);
780
+ * console.log(t1.size); // 4;
775
781
  */
776
782
  merge(anotherTree: BinaryTree<K, V, R>) {
777
783
  this.setMany(anotherTree, []);
@@ -800,6 +806,23 @@ export class BinaryTree<K = any, V = any, R = any>
800
806
  *
801
807
  * @param keyNodeEntryRawOrPredicate - The node to delete.
802
808
  * @returns An array containing deletion results (for compatibility with self-balancing trees).
809
+
810
+
811
+
812
+
813
+
814
+
815
+
816
+
817
+
818
+
819
+
820
+ * @example
821
+ * // Remove a node
822
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
823
+ * tree.delete(3);
824
+ * console.log(tree.has(3)); // false;
825
+ * console.log(tree.size); // 4;
803
826
  */
804
827
  delete(
805
828
  keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
@@ -865,6 +888,16 @@ export class BinaryTree<K = any, V = any, R = any>
865
888
  return deletedResult;
866
889
  }
867
890
 
891
+ /**
892
+ * Search by predicate
893
+
894
+
895
+ * @example
896
+ * // Search by predicate
897
+ * const tree = new BinaryTree<number>([5, 3, 7, 1, 9]);
898
+ * const found = tree.search(n => n!.key > 5, true);
899
+ * console.log(found.length); // >= 1;
900
+ */
868
901
  search(
869
902
  keyNodeEntryOrPredicate:
870
903
  | K
@@ -963,6 +996,19 @@ export class BinaryTree<K = any, V = any, R = any>
963
996
  * @param [startNode=this._root] - The node to start the search from.
964
997
  * @param [iterationType=this.iterationType] - The traversal method.
965
998
  * @returns An array of matching nodes.
999
+
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+ * @example
1008
+ * // Get nodes by condition
1009
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1010
+ * const nodes = tree.getNodes(node => node.key > 3);
1011
+ * console.log(nodes.length); // 2;
966
1012
  */
967
1013
  getNodes(
968
1014
  keyNodeEntryOrPredicate:
@@ -1000,6 +1046,19 @@ export class BinaryTree<K = any, V = any, R = any>
1000
1046
  * @param [startNode=this._root] - The node to start the search from.
1001
1047
  * @param [iterationType=this.iterationType] - The traversal method.
1002
1048
  * @returns The first matching node, or undefined if not found.
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+ * @example
1059
+ * // Get node by key
1060
+ * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
1061
+ * console.log(tree.getNode(2)?.value); // 'child';
1003
1062
  */
1004
1063
  getNode(
1005
1064
  keyNodeEntryOrPredicate:
@@ -1030,6 +1089,22 @@ export class BinaryTree<K = any, V = any, R = any>
1030
1089
  * @param [startNode=this._root] - The node to start searching from (if not in Map mode).
1031
1090
  * @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
1032
1091
  * @returns The associated value, or undefined.
1092
+
1093
+
1094
+
1095
+
1096
+
1097
+
1098
+
1099
+
1100
+
1101
+
1102
+
1103
+ * @example
1104
+ * // Retrieve value by key
1105
+ * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
1106
+ * console.log(tree.get(2)); // 'left';
1107
+ * console.log(tree.get(99)); // undefined;
1033
1108
  */
1034
1109
  override get(
1035
1110
  keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1052,6 +1127,45 @@ export class BinaryTree<K = any, V = any, R = any>
1052
1127
  * @param [startNode] - The node to start the search from.
1053
1128
  * @param [iterationType] - The traversal method.
1054
1129
  * @returns True if a matching node exists, false otherwise.
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+ * @example
1142
+ * // BinaryTree get and has operations
1143
+ * const tree = new BinaryTree(
1144
+ * [
1145
+ * [5, 'five'],
1146
+ * [3, 'three'],
1147
+ * [7, 'seven'],
1148
+ * [1, 'one'],
1149
+ * [4, 'four'],
1150
+ * [6, 'six'],
1151
+ * [8, 'eight']
1152
+ * ],
1153
+ * { isMapMode: false }
1154
+ * );
1155
+ *
1156
+ * // Check if key exists
1157
+ * console.log(tree.has(5)); // true;
1158
+ * console.log(tree.has(10)); // false;
1159
+ *
1160
+ * // Get value by key
1161
+ * console.log(tree.get(3)); // 'three';
1162
+ * console.log(tree.get(7)); // 'seven';
1163
+ * console.log(tree.get(100)); // undefined;
1164
+ *
1165
+ * // Get node structure
1166
+ * const node = tree.getNode(5);
1167
+ * console.log(node?.key); // 5;
1168
+ * console.log(node?.value); // 'five';
1055
1169
  */
1056
1170
  override has(
1057
1171
  keyNodeEntryOrPredicate?:
@@ -1089,6 +1203,20 @@ export class BinaryTree<K = any, V = any, R = any>
1089
1203
  /**
1090
1204
  * Clears the tree of all nodes and values.
1091
1205
  * @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+ * @example
1216
+ * // Remove all nodes
1217
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1218
+ * tree.clear();
1219
+ * console.log(tree.isEmpty()); // true;
1092
1220
  */
1093
1221
  clear() {
1094
1222
  this._clearNodes();
@@ -1100,6 +1228,18 @@ export class BinaryTree<K = any, V = any, R = any>
1100
1228
  * @remarks Time O(1), Space O(1)
1101
1229
  *
1102
1230
  * @returns True if the tree has no nodes, false otherwise.
1231
+
1232
+
1233
+
1234
+
1235
+
1236
+
1237
+
1238
+
1239
+
1240
+ * @example
1241
+ * // Check empty
1242
+ * console.log(new BinaryTree().isEmpty()); // true;
1103
1243
  */
1104
1244
  isEmpty(): boolean {
1105
1245
  return this._size === 0;
@@ -1125,6 +1265,20 @@ export class BinaryTree<K = any, V = any, R = any>
1125
1265
  * @param [startNode=this._root] - The node to start checking from.
1126
1266
  * @param [iterationType=this.iterationType] - The traversal method.
1127
1267
  * @returns True if it's a valid BST, false otherwise.
1268
+
1269
+
1270
+
1271
+
1272
+
1273
+
1274
+
1275
+
1276
+
1277
+ * @example
1278
+ * // Check BST property
1279
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1280
+ * // BinaryTree doesn't guarantee BST order
1281
+ * console.log(typeof tree.isBST()); // 'boolean';
1128
1282
  */
1129
1283
  isBST(
1130
1284
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1176,6 +1330,22 @@ export class BinaryTree<K = any, V = any, R = any>
1176
1330
  * @param dist - The node to find the depth of.
1177
1331
  * @param [startNode=this._root] - The node to measure depth from (defaults to root).
1178
1332
  * @returns The depth (0 if `dist` is `startNode`).
1333
+
1334
+
1335
+
1336
+
1337
+
1338
+
1339
+
1340
+
1341
+
1342
+
1343
+
1344
+ * @example
1345
+ * // Get depth of a node
1346
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1347
+ * const node = tree.getNode(4);
1348
+ * console.log(tree.getDepth(node!)); // 2;
1179
1349
  */
1180
1350
  getDepth(
1181
1351
  dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1201,6 +1371,21 @@ export class BinaryTree<K = any, V = any, R = any>
1201
1371
  * @param [startNode=this._root] - The node to start measuring from.
1202
1372
  * @param [iterationType=this.iterationType] - The traversal method.
1203
1373
  * @returns The height ( -1 for an empty tree, 0 for a single-node tree).
1374
+
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+
1383
+
1384
+
1385
+ * @example
1386
+ * // Get tree height
1387
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1388
+ * console.log(tree.getHeight()); // 2;
1204
1389
  */
1205
1390
  getHeight(
1206
1391
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1466,6 +1651,25 @@ export class BinaryTree<K = any, V = any, R = any>
1466
1651
  return y;
1467
1652
  }
1468
1653
 
1654
+ /**
1655
+ * Depth-first search traversal
1656
+
1657
+
1658
+
1659
+
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+
1666
+
1667
+ * @example
1668
+ * // Depth-first search traversal
1669
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1670
+ * const inOrder = tree.dfs(node => node.key, 'IN');
1671
+ * console.log(inOrder); // [4, 2, 5, 1, 3];
1672
+ */
1469
1673
  dfs(): (K | undefined)[];
1470
1674
 
1471
1675
  dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1511,6 +1715,47 @@ export class BinaryTree<K = any, V = any, R = any>
1511
1715
  return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
1512
1716
  }
1513
1717
 
1718
+ /**
1719
+ * BinaryTree level-order traversal
1720
+
1721
+
1722
+
1723
+
1724
+
1725
+
1726
+
1727
+
1728
+
1729
+
1730
+
1731
+ * @example
1732
+ * // BinaryTree level-order traversal
1733
+ * const tree = new BinaryTree([
1734
+ * [1, 'one'],
1735
+ * [2, 'two'],
1736
+ * [3, 'three'],
1737
+ * [4, 'four'],
1738
+ * [5, 'five'],
1739
+ * [6, 'six'],
1740
+ * [7, 'seven']
1741
+ * ]);
1742
+ *
1743
+ * // Binary tree maintains level-order insertion
1744
+ * // Complete binary tree structure
1745
+ * console.log(tree.size); // 7;
1746
+ *
1747
+ * // Verify all keys are present
1748
+ * console.log(tree.has(1)); // true;
1749
+ * console.log(tree.has(4)); // true;
1750
+ * console.log(tree.has(7)); // true;
1751
+ *
1752
+ * // Iterate through tree
1753
+ * const keys: number[] = [];
1754
+ * for (const [key] of tree) {
1755
+ * keys.push(key);
1756
+ * }
1757
+ * console.log(keys.length); // 7;
1758
+ */
1514
1759
  bfs(): (K | undefined)[];
1515
1760
 
1516
1761
  bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1595,6 +1840,23 @@ export class BinaryTree<K = any, V = any, R = any>
1595
1840
  return ans;
1596
1841
  }
1597
1842
 
1843
+ /**
1844
+ * Get leaf nodes
1845
+
1846
+
1847
+
1848
+
1849
+
1850
+
1851
+
1852
+
1853
+
1854
+ * @example
1855
+ * // Get leaf nodes
1856
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1857
+ * const leafKeys = tree.leaves(node => node.key);
1858
+ * console.log(leafKeys.length); // > 0;
1859
+ */
1598
1860
  leaves(): (K | undefined)[];
1599
1861
 
1600
1862
  leaves<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1605,7 +1867,7 @@ export class BinaryTree<K = any, V = any, R = any>
1605
1867
 
1606
1868
  /**
1607
1869
  * Finds all leaf nodes in the tree.
1608
- * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
1870
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
1609
1871
  *
1610
1872
  * @template C - The type of the callback function.
1611
1873
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -1636,17 +1898,18 @@ export class BinaryTree<K = any, V = any, R = any>
1636
1898
 
1637
1899
  dfs(startNode);
1638
1900
  } else {
1639
- // BFS-based
1640
- const queue = new Queue([startNode]);
1901
+ // DFS-based (stack) to match recursive order
1902
+ const stack = [startNode];
1641
1903
 
1642
- while (queue.length > 0) {
1643
- const cur = queue.shift();
1904
+ while (stack.length > 0) {
1905
+ const cur = stack.pop()!;
1644
1906
  if (this.isRealNode(cur)) {
1645
1907
  if (this.isLeaf(cur)) {
1646
1908
  leaves.push(callback(cur));
1647
1909
  }
1648
- if (this.isRealNode(cur.left)) queue.push(cur.left);
1649
- if (this.isRealNode(cur.right)) queue.push(cur.right);
1910
+ // Push right first so left is processed first (LIFO)
1911
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
1912
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
1650
1913
  }
1651
1914
  }
1652
1915
  }
@@ -1654,6 +1917,23 @@ export class BinaryTree<K = any, V = any, R = any>
1654
1917
  return leaves;
1655
1918
  }
1656
1919
 
1920
+ /**
1921
+ * Level-order grouping
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+ * @example
1931
+ * // Level-order grouping
1932
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1933
+ * const levels = tree.listLevels(node => node.key);
1934
+ * console.log(levels[0]); // [1];
1935
+ * console.log(levels[1].sort()); // [2, 3];
1936
+ */
1657
1937
  listLevels(): (K | undefined)[][];
1658
1938
 
1659
1939
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1731,6 +2011,22 @@ export class BinaryTree<K = any, V = any, R = any>
1731
2011
  return levelsNodes;
1732
2012
  }
1733
2013
 
2014
+ /**
2015
+ * Morris traversal (O(1) space)
2016
+
2017
+
2018
+
2019
+
2020
+
2021
+
2022
+
2023
+
2024
+ * @example
2025
+ * // Morris traversal (O(1) space)
2026
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2027
+ * const result = tree.morris(node => node.key, 'IN');
2028
+ * console.log(result.length); // 3;
2029
+ */
1734
2030
  morris(): (K | undefined)[];
1735
2031
 
1736
2032
  morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1854,6 +2150,21 @@ export class BinaryTree<K = any, V = any, R = any>
1854
2150
  * @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `set`, and `set` is O(M)). Space O(N) for the new tree and the BFS queue.
1855
2151
  *
1856
2152
  * @returns A new, cloned instance of the tree.
2153
+
2154
+
2155
+
2156
+
2157
+
2158
+
2159
+
2160
+
2161
+
2162
+ * @example
2163
+ * // Deep copy
2164
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2165
+ * const copy = tree.clone();
2166
+ * copy.delete(1);
2167
+ * console.log(tree.has(1)); // true;
1857
2168
  */
1858
2169
  clone(): this {
1859
2170
  const out = this._createInstance<K, V, R>();
@@ -1868,6 +2179,20 @@ export class BinaryTree<K = any, V = any, R = any>
1868
2179
  * @param predicate - A function to test each [key, value] pair.
1869
2180
  * @param [thisArg] - `this` context for the predicate.
1870
2181
  * @returns A new, filtered tree.
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+
2188
+
2189
+
2190
+
2191
+ * @example
2192
+ * // Filter nodes by condition
2193
+ * const tree = new BinaryTree<number>([1, 2, 3, 4]);
2194
+ * const result = tree.filter((_, key) => key > 2);
2195
+ * console.log(result.size); // 2;
1871
2196
  */
1872
2197
  filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
1873
2198
  const out = this._createInstance<K, V, R>();
@@ -1887,6 +2212,20 @@ export class BinaryTree<K = any, V = any, R = any>
1887
2212
  * @param [options] - Options for the new tree.
1888
2213
  * @param [thisArg] - `this` context for the callback.
1889
2214
  * @returns A new, mapped tree.
2215
+
2216
+
2217
+
2218
+
2219
+
2220
+
2221
+
2222
+
2223
+
2224
+ * @example
2225
+ * // Transform to new tree
2226
+ * const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
2227
+ * const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
2228
+ * console.log([...mapped.values()]); // contains 11;
1890
2229
  */
1891
2230
  map<MK = K, MV = V, MR = any>(
1892
2231
  cb: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -1939,6 +2278,19 @@ export class BinaryTree<K = any, V = any, R = any>
1939
2278
  *
1940
2279
  * @param [options] - Options to control the output.
1941
2280
  * @param [startNode=this._root] - The node to start printing from.
2281
+
2282
+
2283
+
2284
+
2285
+
2286
+
2287
+
2288
+
2289
+
2290
+ * @example
2291
+ * // Display tree
2292
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2293
+ * expect(() => tree.print()).not.toThrow();
1942
2294
  */
1943
2295
  override print(
1944
2296
  options?: BinaryTreePrintOptions,
@@ -2257,41 +2609,60 @@ export class BinaryTree<K = any, V = any, R = any>
2257
2609
  node: BinaryTreeNode<K, V> | null | undefined,
2258
2610
  options: BinaryTreePrintOptions
2259
2611
  ): NodeDisplayLayout {
2260
- const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2261
- const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0]; // Represents an empty spot
2262
-
2263
- if (node === null && !isShowNull) {
2264
- return emptyDisplayLayout;
2265
- } else if (node === undefined && !isShowUndefined) {
2266
- return emptyDisplayLayout;
2267
- } else if (this.isNIL(node) && !isShowRedBlackNIL) {
2268
- return emptyDisplayLayout;
2269
- } else if (node !== null && node !== undefined) {
2270
- // Real node
2271
- const key = node.key,
2272
- line = this.isNIL(node) ? 'S' : String(key),
2273
- width = line.length;
2274
-
2275
- return _buildNodeDisplay(
2276
- line,
2277
- width,
2278
- this._displayAux(node.left, options),
2279
- this._displayAux(node.right, options)
2280
- );
2281
- } else {
2282
- // Null or Undefined
2283
- const line = node === undefined ? 'U' : 'N',
2284
- width = line.length;
2612
+ const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
2613
+
2614
+ // Iterative post-order: compute display layout bottom-up using an explicit stack.
2615
+ // Stages: 0=process left, 1=process right, 2=merge
2616
+ type Frame = {
2617
+ node: BinaryTreeNode<K, V> | null | undefined;
2618
+ stage: 0 | 1 | 2;
2619
+ leftLayout: NodeDisplayLayout;
2620
+ rightLayout: NodeDisplayLayout;
2621
+ };
2622
+
2623
+ const newFrame = (n: BinaryTreeNode<K, V> | null | undefined): Frame => ({
2624
+ node: n, stage: 0, leftLayout: emptyDisplayLayout, rightLayout: emptyDisplayLayout
2625
+ });
2285
2626
 
2286
- // Treat as a leaf
2287
- return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
2627
+ const stack: Frame[] = [newFrame(node)];
2628
+ let result: NodeDisplayLayout = emptyDisplayLayout;
2629
+
2630
+ const setChildResult = (layout: NodeDisplayLayout) => {
2631
+ if (stack.length === 0) { result = layout; return; }
2632
+ const parent = stack[stack.length - 1];
2633
+ if (parent.stage === 1) parent.leftLayout = layout;
2634
+ else parent.rightLayout = layout;
2635
+ };
2636
+
2637
+ while (stack.length > 0) {
2638
+ const frame = stack[stack.length - 1];
2639
+ const cur = frame.node;
2640
+
2641
+ if (frame.stage === 0) {
2642
+ // Leaf / empty node — resolve immediately
2643
+ if (this._isDisplayLeaf(cur, options)) {
2644
+ stack.pop();
2645
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
2646
+ setChildResult(layout);
2647
+ continue;
2648
+ }
2649
+ frame.stage = 1;
2650
+ stack.push(newFrame(cur!.left));
2651
+ } else if (frame.stage === 1) {
2652
+ frame.stage = 2;
2653
+ stack.push(newFrame(cur!.right));
2654
+ } else {
2655
+ stack.pop();
2656
+ const line = this.isNIL(cur) ? 'S' : String(cur!.key);
2657
+ const layout = BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
2658
+ setChildResult(layout);
2659
+ }
2288
2660
  }
2289
2661
 
2290
- /**
2291
- * (Inner) Builds the display lines for a node.
2292
- * @remarks Time/Space: Proportional to the width and height of the subtrees.
2293
- */
2294
- function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
2662
+ return result;
2663
+ }
2664
+
2665
+ protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
2295
2666
  const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
2296
2667
  const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
2297
2668
  const firstLine =
@@ -2324,7 +2695,57 @@ export class BinaryTree<K = any, V = any, R = any>
2324
2695
  Math.max(leftHeight, rightHeight) + 2,
2325
2696
  leftWidth + Math.floor(width / 2)
2326
2697
  ];
2698
+ }
2699
+
2700
+ /**
2701
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
2702
+ */
2703
+ protected _isDisplayLeaf(
2704
+ node: BinaryTreeNode<K, V> | null | undefined,
2705
+ options: BinaryTreePrintOptions
2706
+ ): boolean {
2707
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2708
+ // Empty/hidden nodes are always leaves
2709
+ if (node === null && !isShowNull) return true;
2710
+ if (node === undefined && !isShowUndefined) return true;
2711
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
2712
+ // Shown null/undefined are leaves (no children to recurse into)
2713
+ if (node === null || node === undefined) return true;
2714
+ // Real node: check if it has any children that would be displayed
2715
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
2716
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
2717
+ return !hasDisplayableLeft && !hasDisplayableRight;
2718
+ }
2719
+
2720
+ protected _hasDisplayableChild(
2721
+ child: BinaryTreeNode<K, V> | null | undefined,
2722
+ options: BinaryTreePrintOptions
2723
+ ): boolean {
2724
+ if (child === null) return !!options.isShowNull;
2725
+ if (child === undefined) return !!options.isShowUndefined;
2726
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
2727
+ return true; // real node is always displayable
2728
+ }
2729
+
2730
+ /**
2731
+ * Resolve a display leaf node to its layout.
2732
+ */
2733
+ protected _resolveDisplayLeaf(
2734
+ node: BinaryTreeNode<K, V> | null | undefined,
2735
+ options: BinaryTreePrintOptions,
2736
+ emptyDisplayLayout: NodeDisplayLayout
2737
+ ): NodeDisplayLayout {
2738
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2739
+ if (node === null && !isShowNull) return emptyDisplayLayout;
2740
+ if (node === undefined && !isShowUndefined) return emptyDisplayLayout;
2741
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
2742
+ if (node !== null && node !== undefined) {
2743
+ const line = this.isNIL(node) ? 'S' : String(node.key);
2744
+ return BinaryTree._buildNodeDisplay(line, line.length, emptyDisplayLayout, emptyDisplayLayout);
2327
2745
  }
2746
+ // Shown null / undefined
2747
+ const line = node === undefined ? 'U' : 'N';
2748
+ return BinaryTree._buildNodeDisplay(line, line.length, [[''], 1, 0, 0], [[''], 1, 0, 0]);
2328
2749
  }
2329
2750
 
2330
2751
  /**