data-structure-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 (80) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +34 -1
  3. package/dist/cjs/index.cjs +10639 -2151
  4. package/dist/cjs-legacy/index.cjs +10694 -2195
  5. package/dist/esm/index.mjs +10639 -2150
  6. package/dist/esm-legacy/index.mjs +10694 -2194
  7. package/dist/types/common/error.d.ts +23 -0
  8. package/dist/types/common/index.d.ts +1 -0
  9. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  10. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  11. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  12. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  13. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  14. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  15. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  16. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  17. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  18. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  19. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  20. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  21. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  22. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  23. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  24. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  25. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  26. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  27. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  28. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  29. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  30. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  31. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  32. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  33. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  34. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  35. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  36. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  37. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  38. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  39. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  40. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  41. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  42. package/dist/umd/data-structure-typed.js +10725 -2221
  43. package/dist/umd/data-structure-typed.min.js +4 -2
  44. package/package.json +5 -4
  45. package/src/common/error.ts +60 -0
  46. package/src/common/index.ts +2 -0
  47. package/src/data-structures/base/iterable-element-base.ts +2 -2
  48. package/src/data-structures/binary-tree/avl-tree.ts +146 -51
  49. package/src/data-structures/binary-tree/binary-indexed-tree.ts +317 -247
  50. package/src/data-structures/binary-tree/binary-tree.ts +567 -121
  51. package/src/data-structures/binary-tree/bst.ts +370 -37
  52. package/src/data-structures/binary-tree/red-black-tree.ts +328 -96
  53. package/src/data-structures/binary-tree/segment-tree.ts +378 -248
  54. package/src/data-structures/binary-tree/tree-map.ts +1411 -13
  55. package/src/data-structures/binary-tree/tree-multi-map.ts +1218 -215
  56. package/src/data-structures/binary-tree/tree-multi-set.ts +959 -69
  57. package/src/data-structures/binary-tree/tree-set.ts +1257 -15
  58. package/src/data-structures/graph/abstract-graph.ts +106 -1
  59. package/src/data-structures/graph/directed-graph.ts +233 -47
  60. package/src/data-structures/graph/map-graph.ts +59 -1
  61. package/src/data-structures/graph/undirected-graph.ts +308 -59
  62. package/src/data-structures/hash/hash-map.ts +254 -79
  63. package/src/data-structures/heap/heap.ts +305 -102
  64. package/src/data-structures/heap/max-heap.ts +48 -3
  65. package/src/data-structures/heap/min-heap.ts +59 -0
  66. package/src/data-structures/linked-list/doubly-linked-list.ts +303 -44
  67. package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
  68. package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
  69. package/src/data-structures/matrix/matrix.ts +433 -22
  70. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  71. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  72. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  73. package/src/data-structures/queue/deque.ts +358 -68
  74. package/src/data-structures/queue/queue.ts +223 -42
  75. package/src/data-structures/stack/stack.ts +184 -32
  76. package/src/data-structures/trie/trie.ts +227 -44
  77. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  78. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  79. package/src/types/data-structures/queue/deque.ts +7 -0
  80. 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,21 @@ 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
+
576
+ * @example
577
+ * // Add a single node
578
+ * const tree = new BinaryTree<number>();
579
+ * tree.add(1);
580
+ * tree.add(2);
581
+ * tree.add(3);
582
+ * console.log(tree.size); // 3;
583
+ * console.log(tree.has(1)); // true;
647
584
  */
648
585
  add(
649
586
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -658,6 +595,41 @@ export class BinaryTree<K = any, V = any, R = any>
658
595
  * @param keyNodeOrEntry - The key, node, or entry to set or update.
659
596
  * @param [value] - The value, if providing just a key.
660
597
  * @returns True if the addition was successful, false otherwise.
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+ * @example
611
+ * // basic BinaryTree creation and insertion
612
+ * // Create a BinaryTree with entries
613
+ * const entries: [number, string][] = [
614
+ * [6, 'six'],
615
+ * [1, 'one'],
616
+ * [2, 'two'],
617
+ * [7, 'seven'],
618
+ * [5, 'five'],
619
+ * [3, 'three'],
620
+ * [4, 'four'],
621
+ * [9, 'nine'],
622
+ * [8, 'eight']
623
+ * ];
624
+ *
625
+ * const tree = new BinaryTree(entries);
626
+ *
627
+ * // Verify size
628
+ * console.log(tree.size); // 9;
629
+ *
630
+ * // Add new element
631
+ * tree.set(10, 'ten');
632
+ * console.log(tree.size); // 10;
661
633
  */
662
634
  set(
663
635
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -670,7 +642,7 @@ export class BinaryTree<K = any, V = any, R = any>
670
642
  if (!this._root) {
671
643
  this._setRoot(newNode);
672
644
  if (this._isMapMode && newNode !== null && newNode !== undefined) this._store.set(newNode.key, newNode);
673
- this._size = 1;
645
+ if (newNode !== null) this._size = 1;
674
646
  return true;
675
647
  }
676
648
 
@@ -708,7 +680,7 @@ export class BinaryTree<K = any, V = any, R = any>
708
680
  potentialParent.right = newNode;
709
681
  }
710
682
  if (this._isMapMode && newNode !== null && newNode !== undefined) this._store.set(newNode.key, newNode);
711
- this._size++;
683
+ if (newNode !== null) this._size++;
712
684
  return true;
713
685
  }
714
686
 
@@ -721,6 +693,21 @@ export class BinaryTree<K = any, V = any, R = any>
721
693
  *
722
694
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
723
695
  * @returns An array of booleans indicating the success of each individual `set` operation.
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+ * @example
707
+ * // Bulk add
708
+ * const tree = new BinaryTree<number>();
709
+ * tree.addMany([1, 2, 3, 4, 5]);
710
+ * console.log(tree.size); // 5;
724
711
  */
725
712
  addMany(
726
713
  keysNodesEntriesOrRaws: Iterable<
@@ -737,6 +724,14 @@ export class BinaryTree<K = any, V = any, R = any>
737
724
  * @param keysNodesEntriesOrRaws - An iterable of items to set or update.
738
725
  * @param [values] - An optional parallel iterable of values.
739
726
  * @returns An array of booleans indicating the success of each individual `set` operation.
727
+
728
+
729
+
730
+ * @example
731
+ * // Set multiple entries
732
+ * const tree = new BinaryTree<number, string>();
733
+ * tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
734
+ * console.log(tree.size); // 3;
740
735
  */
741
736
  setMany(
742
737
  keysNodesEntriesOrRaws: Iterable<
@@ -772,6 +767,22 @@ export class BinaryTree<K = any, V = any, R = any>
772
767
  * @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
768
  *
774
769
  * @param anotherTree - The tree to merge.
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+ * @example
781
+ * // Combine trees
782
+ * const t1 = new BinaryTree<number>([1, 2]);
783
+ * const t2 = new BinaryTree<number>([3, 4]);
784
+ * t1.merge(t2);
785
+ * console.log(t1.size); // 4;
775
786
  */
776
787
  merge(anotherTree: BinaryTree<K, V, R>) {
777
788
  this.setMany(anotherTree, []);
@@ -800,6 +811,24 @@ export class BinaryTree<K = any, V = any, R = any>
800
811
  *
801
812
  * @param keyNodeEntryRawOrPredicate - The node to delete.
802
813
  * @returns An array containing deletion results (for compatibility with self-balancing trees).
814
+
815
+
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+
824
+
825
+
826
+ * @example
827
+ * // Remove a node
828
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
829
+ * tree.delete(3);
830
+ * console.log(tree.has(3)); // false;
831
+ * console.log(tree.size); // 4;
803
832
  */
804
833
  delete(
805
834
  keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
@@ -865,6 +894,17 @@ export class BinaryTree<K = any, V = any, R = any>
865
894
  return deletedResult;
866
895
  }
867
896
 
897
+ /**
898
+ * Search by predicate
899
+
900
+
901
+
902
+ * @example
903
+ * // Search by predicate
904
+ * const tree = new BinaryTree<number>([5, 3, 7, 1, 9]);
905
+ * const found = tree.search(n => n!.key > 5, true);
906
+ * console.log(found.length); // >= 1;
907
+ */
868
908
  search(
869
909
  keyNodeEntryOrPredicate:
870
910
  | K
@@ -963,6 +1003,20 @@ export class BinaryTree<K = any, V = any, R = any>
963
1003
  * @param [startNode=this._root] - The node to start the search from.
964
1004
  * @param [iterationType=this.iterationType] - The traversal method.
965
1005
  * @returns An array of matching nodes.
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+ * @example
1016
+ * // Get nodes by condition
1017
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1018
+ * const nodes = tree.getNodes(node => node.key > 3);
1019
+ * console.log(nodes.length); // 2;
966
1020
  */
967
1021
  getNodes(
968
1022
  keyNodeEntryOrPredicate:
@@ -1000,6 +1054,20 @@ export class BinaryTree<K = any, V = any, R = any>
1000
1054
  * @param [startNode=this._root] - The node to start the search from.
1001
1055
  * @param [iterationType=this.iterationType] - The traversal method.
1002
1056
  * @returns The first matching node, or undefined if not found.
1057
+
1058
+
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+ * @example
1068
+ * // Get node by key
1069
+ * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
1070
+ * console.log(tree.getNode(2)?.value); // 'child';
1003
1071
  */
1004
1072
  getNode(
1005
1073
  keyNodeEntryOrPredicate:
@@ -1030,6 +1098,23 @@ export class BinaryTree<K = any, V = any, R = any>
1030
1098
  * @param [startNode=this._root] - The node to start searching from (if not in Map mode).
1031
1099
  * @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
1032
1100
  * @returns The associated value, or undefined.
1101
+
1102
+
1103
+
1104
+
1105
+
1106
+
1107
+
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+ * @example
1114
+ * // Retrieve value by key
1115
+ * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
1116
+ * console.log(tree.get(2)); // 'left';
1117
+ * console.log(tree.get(99)); // undefined;
1033
1118
  */
1034
1119
  override get(
1035
1120
  keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1052,6 +1137,46 @@ export class BinaryTree<K = any, V = any, R = any>
1052
1137
  * @param [startNode] - The node to start the search from.
1053
1138
  * @param [iterationType] - The traversal method.
1054
1139
  * @returns True if a matching node exists, false otherwise.
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+ * @example
1153
+ * // BinaryTree get and has operations
1154
+ * const tree = new BinaryTree(
1155
+ * [
1156
+ * [5, 'five'],
1157
+ * [3, 'three'],
1158
+ * [7, 'seven'],
1159
+ * [1, 'one'],
1160
+ * [4, 'four'],
1161
+ * [6, 'six'],
1162
+ * [8, 'eight']
1163
+ * ],
1164
+ * { isMapMode: false }
1165
+ * );
1166
+ *
1167
+ * // Check if key exists
1168
+ * console.log(tree.has(5)); // true;
1169
+ * console.log(tree.has(10)); // false;
1170
+ *
1171
+ * // Get value by key
1172
+ * console.log(tree.get(3)); // 'three';
1173
+ * console.log(tree.get(7)); // 'seven';
1174
+ * console.log(tree.get(100)); // undefined;
1175
+ *
1176
+ * // Get node structure
1177
+ * const node = tree.getNode(5);
1178
+ * console.log(node?.key); // 5;
1179
+ * console.log(node?.value); // 'five';
1055
1180
  */
1056
1181
  override has(
1057
1182
  keyNodeEntryOrPredicate?:
@@ -1089,6 +1214,21 @@ export class BinaryTree<K = any, V = any, R = any>
1089
1214
  /**
1090
1215
  * Clears the tree of all nodes and values.
1091
1216
  * @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+ * @example
1228
+ * // Remove all nodes
1229
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1230
+ * tree.clear();
1231
+ * console.log(tree.isEmpty()); // true;
1092
1232
  */
1093
1233
  clear() {
1094
1234
  this._clearNodes();
@@ -1100,6 +1240,19 @@ export class BinaryTree<K = any, V = any, R = any>
1100
1240
  * @remarks Time O(1), Space O(1)
1101
1241
  *
1102
1242
  * @returns True if the tree has no nodes, false otherwise.
1243
+
1244
+
1245
+
1246
+
1247
+
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+ * @example
1254
+ * // Check empty
1255
+ * console.log(new BinaryTree().isEmpty()); // true;
1103
1256
  */
1104
1257
  isEmpty(): boolean {
1105
1258
  return this._size === 0;
@@ -1125,6 +1278,21 @@ export class BinaryTree<K = any, V = any, R = any>
1125
1278
  * @param [startNode=this._root] - The node to start checking from.
1126
1279
  * @param [iterationType=this.iterationType] - The traversal method.
1127
1280
  * @returns True if it's a valid BST, false otherwise.
1281
+
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+ * @example
1292
+ * // Check BST property
1293
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1294
+ * // BinaryTree doesn't guarantee BST order
1295
+ * console.log(typeof tree.isBST()); // 'boolean';
1128
1296
  */
1129
1297
  isBST(
1130
1298
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1176,6 +1344,23 @@ export class BinaryTree<K = any, V = any, R = any>
1176
1344
  * @param dist - The node to find the depth of.
1177
1345
  * @param [startNode=this._root] - The node to measure depth from (defaults to root).
1178
1346
  * @returns The depth (0 if `dist` is `startNode`).
1347
+
1348
+
1349
+
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+
1359
+ * @example
1360
+ * // Get depth of a node
1361
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1362
+ * const node = tree.getNode(4);
1363
+ * console.log(tree.getDepth(node!)); // 2;
1179
1364
  */
1180
1365
  getDepth(
1181
1366
  dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1201,6 +1386,22 @@ export class BinaryTree<K = any, V = any, R = any>
1201
1386
  * @param [startNode=this._root] - The node to start measuring from.
1202
1387
  * @param [iterationType=this.iterationType] - The traversal method.
1203
1388
  * @returns The height ( -1 for an empty tree, 0 for a single-node tree).
1389
+
1390
+
1391
+
1392
+
1393
+
1394
+
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+ * @example
1402
+ * // Get tree height
1403
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1404
+ * console.log(tree.getHeight()); // 2;
1204
1405
  */
1205
1406
  getHeight(
1206
1407
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1466,6 +1667,26 @@ export class BinaryTree<K = any, V = any, R = any>
1466
1667
  return y;
1467
1668
  }
1468
1669
 
1670
+ /**
1671
+ * Depth-first search traversal
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+
1681
+
1682
+
1683
+
1684
+ * @example
1685
+ * // Depth-first search traversal
1686
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1687
+ * const inOrder = tree.dfs(node => node.key, 'IN');
1688
+ * console.log(inOrder); // [4, 2, 5, 1, 3];
1689
+ */
1469
1690
  dfs(): (K | undefined)[];
1470
1691
 
1471
1692
  dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1511,6 +1732,48 @@ export class BinaryTree<K = any, V = any, R = any>
1511
1732
  return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
1512
1733
  }
1513
1734
 
1735
+ /**
1736
+ * BinaryTree level-order traversal
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+ * @example
1750
+ * // BinaryTree level-order traversal
1751
+ * const tree = new BinaryTree([
1752
+ * [1, 'one'],
1753
+ * [2, 'two'],
1754
+ * [3, 'three'],
1755
+ * [4, 'four'],
1756
+ * [5, 'five'],
1757
+ * [6, 'six'],
1758
+ * [7, 'seven']
1759
+ * ]);
1760
+ *
1761
+ * // Binary tree maintains level-order insertion
1762
+ * // Complete binary tree structure
1763
+ * console.log(tree.size); // 7;
1764
+ *
1765
+ * // Verify all keys are present
1766
+ * console.log(tree.has(1)); // true;
1767
+ * console.log(tree.has(4)); // true;
1768
+ * console.log(tree.has(7)); // true;
1769
+ *
1770
+ * // Iterate through tree
1771
+ * const keys: number[] = [];
1772
+ * for (const [key] of tree) {
1773
+ * keys.push(key);
1774
+ * }
1775
+ * console.log(keys.length); // 7;
1776
+ */
1514
1777
  bfs(): (K | undefined)[];
1515
1778
 
1516
1779
  bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1595,6 +1858,24 @@ export class BinaryTree<K = any, V = any, R = any>
1595
1858
  return ans;
1596
1859
  }
1597
1860
 
1861
+ /**
1862
+ * Get leaf nodes
1863
+
1864
+
1865
+
1866
+
1867
+
1868
+
1869
+
1870
+
1871
+
1872
+
1873
+ * @example
1874
+ * // Get leaf nodes
1875
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1876
+ * const leafKeys = tree.leaves(node => node.key);
1877
+ * console.log(leafKeys.length); // > 0;
1878
+ */
1598
1879
  leaves(): (K | undefined)[];
1599
1880
 
1600
1881
  leaves<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1605,7 +1886,7 @@ export class BinaryTree<K = any, V = any, R = any>
1605
1886
 
1606
1887
  /**
1607
1888
  * 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.
1889
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
1609
1890
  *
1610
1891
  * @template C - The type of the callback function.
1611
1892
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -1636,17 +1917,18 @@ export class BinaryTree<K = any, V = any, R = any>
1636
1917
 
1637
1918
  dfs(startNode);
1638
1919
  } else {
1639
- // BFS-based
1640
- const queue = new Queue([startNode]);
1920
+ // DFS-based (stack) to match recursive order
1921
+ const stack = [startNode];
1641
1922
 
1642
- while (queue.length > 0) {
1643
- const cur = queue.shift();
1923
+ while (stack.length > 0) {
1924
+ const cur = stack.pop()!;
1644
1925
  if (this.isRealNode(cur)) {
1645
1926
  if (this.isLeaf(cur)) {
1646
1927
  leaves.push(callback(cur));
1647
1928
  }
1648
- if (this.isRealNode(cur.left)) queue.push(cur.left);
1649
- if (this.isRealNode(cur.right)) queue.push(cur.right);
1929
+ // Push right first so left is processed first (LIFO)
1930
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
1931
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
1650
1932
  }
1651
1933
  }
1652
1934
  }
@@ -1654,6 +1936,24 @@ export class BinaryTree<K = any, V = any, R = any>
1654
1936
  return leaves;
1655
1937
  }
1656
1938
 
1939
+ /**
1940
+ * Level-order grouping
1941
+
1942
+
1943
+
1944
+
1945
+
1946
+
1947
+
1948
+
1949
+
1950
+ * @example
1951
+ * // Level-order grouping
1952
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1953
+ * const levels = tree.listLevels(node => node.key);
1954
+ * console.log(levels[0]); // [1];
1955
+ * console.log(levels[1].sort()); // [2, 3];
1956
+ */
1657
1957
  listLevels(): (K | undefined)[][];
1658
1958
 
1659
1959
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1731,6 +2031,23 @@ export class BinaryTree<K = any, V = any, R = any>
1731
2031
  return levelsNodes;
1732
2032
  }
1733
2033
 
2034
+ /**
2035
+ * Morris traversal (O(1) space)
2036
+
2037
+
2038
+
2039
+
2040
+
2041
+
2042
+
2043
+
2044
+
2045
+ * @example
2046
+ * // Morris traversal (O(1) space)
2047
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2048
+ * const result = tree.morris(node => node.key, 'IN');
2049
+ * console.log(result.length); // 3;
2050
+ */
1734
2051
  morris(): (K | undefined)[];
1735
2052
 
1736
2053
  morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
@@ -1854,6 +2171,22 @@ export class BinaryTree<K = any, V = any, R = any>
1854
2171
  * @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
2172
  *
1856
2173
  * @returns A new, cloned instance of the tree.
2174
+
2175
+
2176
+
2177
+
2178
+
2179
+
2180
+
2181
+
2182
+
2183
+
2184
+ * @example
2185
+ * // Deep copy
2186
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2187
+ * const copy = tree.clone();
2188
+ * copy.delete(1);
2189
+ * console.log(tree.has(1)); // true;
1857
2190
  */
1858
2191
  clone(): this {
1859
2192
  const out = this._createInstance<K, V, R>();
@@ -1868,6 +2201,21 @@ export class BinaryTree<K = any, V = any, R = any>
1868
2201
  * @param predicate - A function to test each [key, value] pair.
1869
2202
  * @param [thisArg] - `this` context for the predicate.
1870
2203
  * @returns A new, filtered tree.
2204
+
2205
+
2206
+
2207
+
2208
+
2209
+
2210
+
2211
+
2212
+
2213
+
2214
+ * @example
2215
+ * // Filter nodes by condition
2216
+ * const tree = new BinaryTree<number>([1, 2, 3, 4]);
2217
+ * const result = tree.filter((_, key) => key > 2);
2218
+ * console.log(result.size); // 2;
1871
2219
  */
1872
2220
  filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
1873
2221
  const out = this._createInstance<K, V, R>();
@@ -1887,6 +2235,21 @@ export class BinaryTree<K = any, V = any, R = any>
1887
2235
  * @param [options] - Options for the new tree.
1888
2236
  * @param [thisArg] - `this` context for the callback.
1889
2237
  * @returns A new, mapped tree.
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+
2244
+
2245
+
2246
+
2247
+
2248
+ * @example
2249
+ * // Transform to new tree
2250
+ * const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
2251
+ * const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
2252
+ * console.log([...mapped.values()]); // contains 11;
1890
2253
  */
1891
2254
  map<MK = K, MV = V, MR = any>(
1892
2255
  cb: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -1939,6 +2302,20 @@ export class BinaryTree<K = any, V = any, R = any>
1939
2302
  *
1940
2303
  * @param [options] - Options to control the output.
1941
2304
  * @param [startNode=this._root] - The node to start printing from.
2305
+
2306
+
2307
+
2308
+
2309
+
2310
+
2311
+
2312
+
2313
+
2314
+
2315
+ * @example
2316
+ * // Display tree
2317
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2318
+ * expect(() => tree.print()).not.toThrow();
1942
2319
  */
1943
2320
  override print(
1944
2321
  options?: BinaryTreePrintOptions,
@@ -2257,41 +2634,60 @@ export class BinaryTree<K = any, V = any, R = any>
2257
2634
  node: BinaryTreeNode<K, V> | null | undefined,
2258
2635
  options: BinaryTreePrintOptions
2259
2636
  ): 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;
2637
+ const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
2638
+
2639
+ // Iterative post-order: compute display layout bottom-up using an explicit stack.
2640
+ // Stages: 0=process left, 1=process right, 2=merge
2641
+ type Frame = {
2642
+ node: BinaryTreeNode<K, V> | null | undefined;
2643
+ stage: 0 | 1 | 2;
2644
+ leftLayout: NodeDisplayLayout;
2645
+ rightLayout: NodeDisplayLayout;
2646
+ };
2647
+
2648
+ const newFrame = (n: BinaryTreeNode<K, V> | null | undefined): Frame => ({
2649
+ node: n, stage: 0, leftLayout: emptyDisplayLayout, rightLayout: emptyDisplayLayout
2650
+ });
2285
2651
 
2286
- // Treat as a leaf
2287
- return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
2652
+ const stack: Frame[] = [newFrame(node)];
2653
+ let result: NodeDisplayLayout = emptyDisplayLayout;
2654
+
2655
+ const setChildResult = (layout: NodeDisplayLayout) => {
2656
+ if (stack.length === 0) { result = layout; return; }
2657
+ const parent = stack[stack.length - 1];
2658
+ if (parent.stage === 1) parent.leftLayout = layout;
2659
+ else parent.rightLayout = layout;
2660
+ };
2661
+
2662
+ while (stack.length > 0) {
2663
+ const frame = stack[stack.length - 1];
2664
+ const cur = frame.node;
2665
+
2666
+ if (frame.stage === 0) {
2667
+ // Leaf / empty node — resolve immediately
2668
+ if (this._isDisplayLeaf(cur, options)) {
2669
+ stack.pop();
2670
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
2671
+ setChildResult(layout);
2672
+ continue;
2673
+ }
2674
+ frame.stage = 1;
2675
+ stack.push(newFrame(cur!.left));
2676
+ } else if (frame.stage === 1) {
2677
+ frame.stage = 2;
2678
+ stack.push(newFrame(cur!.right));
2679
+ } else {
2680
+ stack.pop();
2681
+ const line = this.isNIL(cur) ? 'S' : String(cur!.key);
2682
+ const layout = BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
2683
+ setChildResult(layout);
2684
+ }
2288
2685
  }
2289
2686
 
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) {
2687
+ return result;
2688
+ }
2689
+
2690
+ protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
2295
2691
  const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
2296
2692
  const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
2297
2693
  const firstLine =
@@ -2324,7 +2720,57 @@ export class BinaryTree<K = any, V = any, R = any>
2324
2720
  Math.max(leftHeight, rightHeight) + 2,
2325
2721
  leftWidth + Math.floor(width / 2)
2326
2722
  ];
2723
+ }
2724
+
2725
+ /**
2726
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
2727
+ */
2728
+ protected _isDisplayLeaf(
2729
+ node: BinaryTreeNode<K, V> | null | undefined,
2730
+ options: BinaryTreePrintOptions
2731
+ ): boolean {
2732
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2733
+ // Empty/hidden nodes are always leaves
2734
+ if (node === null && !isShowNull) return true;
2735
+ if (node === undefined && !isShowUndefined) return true;
2736
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
2737
+ // Shown null/undefined are leaves (no children to recurse into)
2738
+ if (node === null || node === undefined) return true;
2739
+ // Real node: check if it has any children that would be displayed
2740
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
2741
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
2742
+ return !hasDisplayableLeft && !hasDisplayableRight;
2743
+ }
2744
+
2745
+ protected _hasDisplayableChild(
2746
+ child: BinaryTreeNode<K, V> | null | undefined,
2747
+ options: BinaryTreePrintOptions
2748
+ ): boolean {
2749
+ if (child === null) return !!options.isShowNull;
2750
+ if (child === undefined) return !!options.isShowUndefined;
2751
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
2752
+ return true; // real node is always displayable
2753
+ }
2754
+
2755
+ /**
2756
+ * Resolve a display leaf node to its layout.
2757
+ */
2758
+ protected _resolveDisplayLeaf(
2759
+ node: BinaryTreeNode<K, V> | null | undefined,
2760
+ options: BinaryTreePrintOptions,
2761
+ emptyDisplayLayout: NodeDisplayLayout
2762
+ ): NodeDisplayLayout {
2763
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2764
+ if (node === null && !isShowNull) return emptyDisplayLayout;
2765
+ if (node === undefined && !isShowUndefined) return emptyDisplayLayout;
2766
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
2767
+ if (node !== null && node !== undefined) {
2768
+ const line = this.isNIL(node) ? 'S' : String(node.key);
2769
+ return BinaryTree._buildNodeDisplay(line, line.length, emptyDisplayLayout, emptyDisplayLayout);
2327
2770
  }
2771
+ // Shown null / undefined
2772
+ const line = node === undefined ? 'U' : 'N';
2773
+ return BinaryTree._buildNodeDisplay(line, line.length, [[''], 1, 0, 0], [[''], 1, 0, 0]);
2328
2774
  }
2329
2775
 
2330
2776
  /**