data-structure-typed 2.5.3 → 2.6.1

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 (158) hide show
  1. package/.github/workflows/ci.yml +7 -2
  2. package/.github/workflows/release-package.yml +9 -2
  3. package/.husky/pre-commit +3 -0
  4. package/CHANGELOG.md +1 -1
  5. package/MIGRATION.md +48 -0
  6. package/README.md +20 -2
  7. package/README_CN.md +20 -2
  8. package/SPECIFICATION.md +24 -0
  9. package/SPECIFICATION.zh-CN.md +24 -0
  10. package/dist/cjs/binary-tree.cjs +1897 -19
  11. package/dist/cjs/graph.cjs +174 -0
  12. package/dist/cjs/hash.cjs +33 -0
  13. package/dist/cjs/heap.cjs +71 -0
  14. package/dist/cjs/index.cjs +2383 -3
  15. package/dist/cjs/linked-list.cjs +224 -2
  16. package/dist/cjs/matrix.cjs +24 -0
  17. package/dist/cjs/priority-queue.cjs +71 -0
  18. package/dist/cjs/queue.cjs +221 -1
  19. package/dist/cjs/stack.cjs +59 -0
  20. package/dist/cjs/trie.cjs +62 -0
  21. package/dist/cjs-legacy/binary-tree.cjs +1897 -19
  22. package/dist/cjs-legacy/graph.cjs +174 -0
  23. package/dist/cjs-legacy/hash.cjs +33 -0
  24. package/dist/cjs-legacy/heap.cjs +71 -0
  25. package/dist/cjs-legacy/index.cjs +2383 -3
  26. package/dist/cjs-legacy/linked-list.cjs +224 -2
  27. package/dist/cjs-legacy/matrix.cjs +24 -0
  28. package/dist/cjs-legacy/priority-queue.cjs +71 -0
  29. package/dist/cjs-legacy/queue.cjs +221 -1
  30. package/dist/cjs-legacy/stack.cjs +59 -0
  31. package/dist/cjs-legacy/trie.cjs +62 -0
  32. package/dist/esm/binary-tree.mjs +1897 -19
  33. package/dist/esm/graph.mjs +174 -0
  34. package/dist/esm/hash.mjs +33 -0
  35. package/dist/esm/heap.mjs +71 -0
  36. package/dist/esm/index.mjs +2383 -3
  37. package/dist/esm/linked-list.mjs +224 -2
  38. package/dist/esm/matrix.mjs +24 -0
  39. package/dist/esm/priority-queue.mjs +71 -0
  40. package/dist/esm/queue.mjs +221 -1
  41. package/dist/esm/stack.mjs +59 -0
  42. package/dist/esm/trie.mjs +62 -0
  43. package/dist/esm-legacy/binary-tree.mjs +1897 -19
  44. package/dist/esm-legacy/graph.mjs +174 -0
  45. package/dist/esm-legacy/hash.mjs +33 -0
  46. package/dist/esm-legacy/heap.mjs +71 -0
  47. package/dist/esm-legacy/index.mjs +2383 -3
  48. package/dist/esm-legacy/linked-list.mjs +224 -2
  49. package/dist/esm-legacy/matrix.mjs +24 -0
  50. package/dist/esm-legacy/priority-queue.mjs +71 -0
  51. package/dist/esm-legacy/queue.mjs +221 -1
  52. package/dist/esm-legacy/stack.mjs +59 -0
  53. package/dist/esm-legacy/trie.mjs +62 -0
  54. package/dist/types/data-structures/base/iterable-element-base.d.ts +17 -0
  55. package/dist/types/data-structures/base/linear-base.d.ts +6 -0
  56. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +36 -0
  57. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
  58. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +75 -0
  59. package/dist/types/data-structures/binary-tree/bst.d.ts +72 -0
  60. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
  61. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
  62. package/dist/types/data-structures/binary-tree/tree-map.d.ts +375 -0
  63. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +389 -0
  64. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +330 -0
  65. package/dist/types/data-structures/binary-tree/tree-set.d.ts +438 -0
  66. package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
  67. package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
  68. package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
  69. package/dist/types/data-structures/heap/heap.d.ts +42 -0
  70. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -2
  71. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
  72. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
  73. package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
  74. package/dist/types/data-structures/queue/deque.d.ts +90 -1
  75. package/dist/types/data-structures/queue/queue.d.ts +36 -0
  76. package/dist/types/data-structures/stack/stack.d.ts +30 -0
  77. package/dist/types/data-structures/trie/trie.d.ts +36 -0
  78. package/dist/umd/data-structure-typed.js +2383 -3
  79. package/dist/umd/data-structure-typed.min.js +3 -3
  80. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
  81. package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
  82. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
  83. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
  84. package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
  85. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
  86. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
  87. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
  88. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  89. package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
  90. package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
  91. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
  92. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
  93. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
  94. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +30 -26
  95. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
  96. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
  97. package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
  98. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
  99. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
  100. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
  101. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
  102. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
  103. package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
  104. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
  105. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
  106. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
  107. package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
  108. package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
  109. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
  110. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
  111. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
  112. package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
  113. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
  114. package/jest.integration.config.js +1 -2
  115. package/package.json +51 -50
  116. package/src/common/error.ts +15 -32
  117. package/src/common/index.ts +0 -3
  118. package/src/data-structures/base/iterable-element-base.ts +32 -3
  119. package/src/data-structures/base/linear-base.ts +13 -36
  120. package/src/data-structures/binary-tree/avl-tree.ts +31 -493
  121. package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -530
  122. package/src/data-structures/binary-tree/binary-tree.ts +326 -1236
  123. package/src/data-structures/binary-tree/bst.ts +158 -1010
  124. package/src/data-structures/binary-tree/red-black-tree.ts +451 -1233
  125. package/src/data-structures/binary-tree/segment-tree.ts +73 -333
  126. package/src/data-structures/binary-tree/tree-map.ts +462 -4749
  127. package/src/data-structures/binary-tree/tree-multi-map.ts +310 -4530
  128. package/src/data-structures/binary-tree/tree-multi-set.ts +300 -3652
  129. package/src/data-structures/binary-tree/tree-set.ts +437 -4443
  130. package/src/data-structures/graph/abstract-graph.ts +98 -167
  131. package/src/data-structures/graph/directed-graph.ts +137 -532
  132. package/src/data-structures/graph/map-graph.ts +0 -3
  133. package/src/data-structures/graph/undirected-graph.ts +132 -484
  134. package/src/data-structures/hash/hash-map.ts +154 -549
  135. package/src/data-structures/heap/heap.ts +200 -753
  136. package/src/data-structures/linked-list/doubly-linked-list.ts +153 -809
  137. package/src/data-structures/linked-list/singly-linked-list.ts +122 -749
  138. package/src/data-structures/linked-list/skip-linked-list.ts +211 -864
  139. package/src/data-structures/matrix/matrix.ts +179 -494
  140. package/src/data-structures/matrix/navigator.ts +0 -1
  141. package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
  142. package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
  143. package/src/data-structures/priority-queue/priority-queue.ts +1 -2
  144. package/src/data-structures/queue/deque.ts +241 -807
  145. package/src/data-structures/queue/queue.ts +102 -589
  146. package/src/data-structures/stack/stack.ts +76 -475
  147. package/src/data-structures/trie/trie.ts +98 -592
  148. package/src/types/common.ts +0 -10
  149. package/src/types/data-structures/binary-tree/bst.ts +0 -7
  150. package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
  151. package/src/types/data-structures/graph/abstract-graph.ts +0 -2
  152. package/src/types/data-structures/hash/hash-map.ts +0 -3
  153. package/src/types/data-structures/hash/index.ts +0 -1
  154. package/src/types/data-structures/matrix/navigator.ts +0 -2
  155. package/src/types/utils/utils.ts +0 -7
  156. package/src/types/utils/validate-type.ts +0 -7
  157. package/src/utils/number.ts +0 -2
  158. package/src/utils/utils.ts +0 -5
@@ -10,7 +10,8 @@ import type {
10
10
  BinaryTreeDeleteResult,
11
11
  BinaryTreeOptions,
12
12
  BinaryTreePrintOptions,
13
- BTNEntry, BTNRep,
13
+ BTNEntry,
14
+ BTNRep,
14
15
  DFSOrderPattern,
15
16
  DFSStackItem,
16
17
  EntryCallback,
@@ -272,6 +273,10 @@ export class BinaryTree<K = any, V = any, R = any>
272
273
  implements IBinaryTree<K, V, R>
273
274
  {
274
275
  iterationType: IterationType = 'ITERATIVE';
276
+ protected readonly _isMapMode: boolean = true;
277
+ protected readonly _isDuplicate: boolean = false;
278
+ protected readonly _NIL = new BinaryTreeNode<K, V>(NaN as K);
279
+ protected readonly _toEntryFn?: ToEntryFn<K, V, R>;
275
280
 
276
281
  /**
277
282
  * Creates an instance of BinaryTree.
@@ -299,7 +304,8 @@ export class BinaryTree<K = any, V = any, R = any>
299
304
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
300
305
  }
301
306
 
302
- protected readonly _isMapMode: boolean = true;
307
+ // Map mode acceleration store:
308
+ // - isMapMode=false: unused
303
309
 
304
310
  /**
305
311
  * Gets whether the tree is in Map mode.
@@ -311,8 +317,6 @@ export class BinaryTree<K = any, V = any, R = any>
311
317
  return this._isMapMode;
312
318
  }
313
319
 
314
- protected readonly _isDuplicate: boolean = false;
315
-
316
320
  /**
317
321
  * Gets whether the tree allows duplicate keys.
318
322
  * @remarks Time O(1)
@@ -323,8 +327,6 @@ export class BinaryTree<K = any, V = any, R = any>
323
327
  return this._isDuplicate;
324
328
  }
325
329
 
326
- // Map mode acceleration store:
327
- // - isMapMode=false: unused
328
330
  // - isMapMode=true: key -> node reference (O(1) has/getNode + fast get)
329
331
  protected _store = new Map<K, BinaryTreeNode<K, V>>();
330
332
 
@@ -362,8 +364,6 @@ export class BinaryTree<K = any, V = any, R = any>
362
364
  return this._size;
363
365
  }
364
366
 
365
- protected readonly _NIL = new BinaryTreeNode<K, V>(NaN as K);
366
-
367
367
  /**
368
368
  * Gets the sentinel NIL node (used in self-balancing trees like Red-Black Tree).
369
369
  * @remarks Time O(1)
@@ -374,8 +374,6 @@ export class BinaryTree<K = any, V = any, R = any>
374
374
  return this._NIL;
375
375
  }
376
376
 
377
- protected readonly _toEntryFn?: ToEntryFn<K, V, R>;
378
-
379
377
  /**
380
378
  * Gets the function used to convert raw data objects (R) into [key, value] entries.
381
379
  * @remarks Time O(1)
@@ -386,6 +384,39 @@ export class BinaryTree<K = any, V = any, R = any>
386
384
  return this._toEntryFn;
387
385
  }
388
386
 
387
+ protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
388
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
389
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
390
+ const firstLine =
391
+ ' '.repeat(Math.max(0, leftMiddle + 1)) +
392
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +
393
+ line +
394
+ '_'.repeat(Math.max(0, rightMiddle)) +
395
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
396
+
397
+ const secondLine =
398
+ (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth)) +
399
+ ' '.repeat(width) +
400
+ (rightHeight > 0
401
+ ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1)
402
+ : ' '.repeat(rightWidth));
403
+
404
+ const mergedLines = [firstLine, secondLine];
405
+
406
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
407
+ const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
408
+ const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
409
+ mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
410
+ }
411
+
412
+ return <NodeDisplayLayout>[
413
+ mergedLines,
414
+ leftWidth + width + rightWidth,
415
+ Math.max(leftHeight, rightHeight) + 2,
416
+ leftWidth + Math.floor(width / 2)
417
+ ];
418
+ }
419
+
389
420
  /**
390
421
  * (Protected) Creates a new node.
391
422
  * @remarks Time O(1), Space O(1)
@@ -566,52 +597,16 @@ export class BinaryTree<K = any, V = any, R = any>
566
597
  *
567
598
  * @param keyNodeOrEntry - The key, node, or entry to add.
568
599
  * @returns True if the addition was successful, false otherwise.
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
- * @example
604
- * // Add a single node
605
- * const tree = new BinaryTree<number>();
606
- * tree.add(1);
607
- * tree.add(2);
608
- * tree.add(3);
609
- * console.log(tree.size); // 3;
610
- * console.log(tree.has(1)); // true;
611
- */
612
- add(
613
- keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
614
- ): boolean {
600
+ * @example
601
+ * // Add a single node
602
+ * const tree = new BinaryTree<number>();
603
+ * tree.add(1);
604
+ * tree.add(2);
605
+ * tree.add(3);
606
+ * console.log(tree.size); // 3;
607
+ * console.log(tree.has(1)); // true;
608
+ */
609
+ add(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
615
610
  return this.set(keyNodeOrEntry);
616
611
  }
617
612
 
@@ -622,74 +617,34 @@ export class BinaryTree<K = any, V = any, R = any>
622
617
  * @param keyNodeOrEntry - The key, node, or entry to set or update.
623
618
  * @param [value] - The value, if providing just a key.
624
619
  * @returns True if the addition was successful, false otherwise.
625
-
626
-
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
- * @example
665
- * // basic BinaryTree creation and insertion
666
- * // Create a BinaryTree with entries
667
- * const entries: [number, string][] = [
668
- * [6, 'six'],
669
- * [1, 'one'],
670
- * [2, 'two'],
671
- * [7, 'seven'],
672
- * [5, 'five'],
673
- * [3, 'three'],
674
- * [4, 'four'],
675
- * [9, 'nine'],
676
- * [8, 'eight']
677
- * ];
678
- *
679
- * const tree = new BinaryTree(entries);
680
- *
681
- * // Verify size
682
- * console.log(tree.size); // 9;
683
- *
684
- * // Add new element
685
- * tree.set(10, 'ten');
686
- * console.log(tree.size); // 10;
620
+ * @example
621
+ * // basic BinaryTree creation and insertion
622
+ * // Create a BinaryTree with entries
623
+ * const entries: [number, string][] = [
624
+ * [6, 'six'],
625
+ * [1, 'one'],
626
+ * [2, 'two'],
627
+ * [7, 'seven'],
628
+ * [5, 'five'],
629
+ * [3, 'three'],
630
+ * [4, 'four'],
631
+ * [9, 'nine'],
632
+ * [8, 'eight']
633
+ * ];
634
+ *
635
+ * const tree = new BinaryTree(entries);
636
+ *
637
+ * // Verify size
638
+ * console.log(tree.size); // 9;
639
+ *
640
+ * // Add new element
641
+ * tree.set(10, 'ten');
642
+ * console.log(tree.size); // 10;
687
643
  */
688
644
  set(
689
645
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
690
646
  value?: V
691
647
  ): boolean {
692
-
693
648
  const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
694
649
  if (newNode === undefined) return false;
695
650
 
@@ -747,48 +702,11 @@ export class BinaryTree<K = any, V = any, R = any>
747
702
  *
748
703
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
749
704
  * @returns An array of booleans indicating the success of each individual `set` operation.
750
-
751
-
752
-
753
-
754
-
755
-
756
-
757
-
758
-
759
-
760
-
761
-
762
-
763
-
764
-
765
-
766
-
767
-
768
-
769
-
770
-
771
-
772
-
773
-
774
-
775
-
776
-
777
-
778
-
779
-
780
-
781
-
782
-
783
-
784
-
785
-
786
-
787
- * @example
788
- * // Bulk add
789
- * const tree = new BinaryTree<number>();
790
- * tree.addMany([1, 2, 3, 4, 5]);
791
- * console.log(tree.size); // 5;
705
+ * @example
706
+ * // Bulk add
707
+ * const tree = new BinaryTree<number>();
708
+ * tree.addMany([1, 2, 3, 4, 5]);
709
+ * console.log(tree.size); // 5;
792
710
  */
793
711
  addMany(
794
712
  keysNodesEntriesOrRaws: Iterable<
@@ -805,41 +723,15 @@ export class BinaryTree<K = any, V = any, R = any>
805
723
  * @param keysNodesEntriesOrRaws - An iterable of items to set or update.
806
724
  * @param [values] - An optional parallel iterable of values.
807
725
  * @returns An array of booleans indicating the success of each individual `set` operation.
808
-
809
-
810
-
811
-
812
-
813
-
814
-
815
-
816
-
817
-
818
-
819
-
820
-
821
-
822
-
823
-
824
-
825
-
826
-
827
-
828
-
829
-
830
-
831
-
832
-
833
-
834
-
835
-
836
-
837
-
838
- * @example
839
- * // Set multiple entries
840
- * const tree = new BinaryTree<number, string>();
841
- * tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
842
- * console.log(tree.size); // 3;
726
+ * @example
727
+ * // Set multiple entries
728
+ * const tree = new BinaryTree<number, string>();
729
+ * tree.setMany([
730
+ * [1, 'a'],
731
+ * [2, 'b'],
732
+ * [3, 'c']
733
+ * ]);
734
+ * console.log(tree.size); // 3;
843
735
  */
844
736
  setMany(
845
737
  keysNodesEntriesOrRaws: Iterable<
@@ -875,166 +767,29 @@ export class BinaryTree<K = any, V = any, R = any>
875
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`).
876
768
  *
877
769
  * @param anotherTree - The tree to merge.
878
-
879
-
880
-
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
-
891
-
892
-
893
-
894
-
895
-
896
-
897
-
898
-
899
-
900
-
901
-
902
-
903
-
904
-
905
-
906
-
907
-
908
-
909
-
910
-
911
-
912
-
913
-
914
-
915
- * @example
916
- * // Combine trees
917
- * const t1 = new BinaryTree<number>([1, 2]);
918
- * const t2 = new BinaryTree<number>([3, 4]);
919
- * t1.merge(t2);
920
- * console.log(t1.size); // 4;
770
+ * @example
771
+ * // Combine trees
772
+ * const t1 = new BinaryTree<number>([1, 2]);
773
+ * const t2 = new BinaryTree<number>([3, 4]);
774
+ * t1.merge(t2);
775
+ * console.log(t1.size); // 4;
921
776
  */
922
777
  merge(anotherTree: BinaryTree<K, V, R>) {
923
778
  this.setMany(anotherTree, []);
924
779
  }
925
780
 
926
- /**
927
- * Deletes a node from the tree (internal, returns balancing metadata).
928
- * @remarks Time O(N) — O(N) to find the node + O(H) for predecessor swap. Space O(1). BST/Red-Black Tree/AVL Tree subclasses override to O(log N).
929
- * @internal Used by AVL/BST subclasses that need balancing metadata after deletion.
930
- *
931
- * @param keyNodeEntryRawOrPredicate - The node to delete.
932
- * @returns An array containing deletion results with balancing metadata.
933
- */
934
- protected _deleteInternal(
935
- keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
936
- ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
937
- const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
938
- if (!this._root) return deletedResult;
939
-
940
- const curr = this.getNode(keyNodeEntryRawOrPredicate);
941
- if (!curr) return deletedResult;
942
-
943
- const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;
944
- let needBalanced: BinaryTreeNode<K, V> | undefined;
945
- let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;
946
-
947
- if (!curr.left && !curr.right && !parent) {
948
- this._setRoot(undefined);
949
- } else if (curr.left) {
950
- const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
951
- if (leftSubTreeRightMost) {
952
- const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
953
- orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
954
-
955
- if (this._isMapMode) {
956
- this._store.set(curr.key, curr);
957
- this._store.set(leftSubTreeRightMost.key, leftSubTreeRightMost);
958
- }
959
-
960
- if (parentOfLeftSubTreeMax) {
961
- if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
962
- parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
963
- else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
964
- needBalanced = parentOfLeftSubTreeMax;
965
- }
966
- }
967
- } else if (parent) {
968
- const { familyPosition: fp } = curr;
969
- if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
970
- parent.left = curr.right;
971
- } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {
972
- parent.right = curr.right;
973
- }
974
- needBalanced = parent;
975
- } else {
976
- this._setRoot(curr.right);
977
- curr.right = undefined;
978
- }
979
-
980
- this._size = this._size - 1;
981
-
982
- deletedResult.push({ deleted: orgCurrent, needBalanced });
983
- if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);
984
- return deletedResult;
985
- }
986
-
987
781
  /**
988
782
  * Deletes a node from the tree.
989
783
  * @remarks Time O(N) — O(N) to find the node + O(H) for predecessor swap. Space O(1). BST/Red-Black Tree/AVL Tree subclasses override to O(log N).
990
784
  *
991
785
  * @param keyNodeEntryRawOrPredicate - The node to delete.
992
786
  * @returns True if the node was found and deleted, false otherwise.
993
-
994
-
995
-
996
-
997
-
998
-
999
-
1000
-
1001
-
1002
-
1003
-
1004
-
1005
-
1006
-
1007
-
1008
-
1009
-
1010
-
1011
-
1012
-
1013
-
1014
-
1015
-
1016
-
1017
-
1018
-
1019
-
1020
-
1021
-
1022
-
1023
-
1024
-
1025
-
1026
-
1027
-
1028
-
1029
-
1030
-
1031
-
1032
- * @example
1033
- * // Remove a node
1034
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1035
- * tree.delete(3);
1036
- * console.log(tree.has(3)); // false;
1037
- * console.log(tree.size); // 4;
787
+ * @example
788
+ * // Remove a node
789
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
790
+ * tree.delete(3);
791
+ * console.log(tree.has(3)); // false;
792
+ * console.log(tree.size); // 4;
1038
793
  */
1039
794
  delete(
1040
795
  keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
@@ -1042,43 +797,13 @@ export class BinaryTree<K = any, V = any, R = any>
1042
797
  return this._deleteInternal(keyNodeEntryRawOrPredicate).length > 0;
1043
798
  }
1044
799
 
1045
- /**
800
+ /**
1046
801
  * Search by predicate
1047
-
1048
-
1049
-
1050
-
1051
-
1052
-
1053
-
1054
-
1055
-
1056
-
1057
-
1058
-
1059
-
1060
-
1061
-
1062
-
1063
-
1064
-
1065
-
1066
-
1067
-
1068
-
1069
-
1070
-
1071
-
1072
-
1073
-
1074
-
1075
-
1076
-
1077
- * @example
1078
- * // Search by predicate
1079
- * const tree = new BinaryTree<number>([5, 3, 7, 1, 9]);
1080
- * const found = tree.search(n => n!.key > 5, true);
1081
- * console.log(found.length); // >= 1;
802
+ * @example
803
+ * // Search by predicate
804
+ * const tree = new BinaryTree<number>([5, 3, 7, 1, 9]);
805
+ * const found = tree.search(n => n!.key > 5, true);
806
+ * console.log(found.length); // >= 1;
1082
807
  */
1083
808
  search(
1084
809
  keyNodeEntryOrPredicate:
@@ -1178,47 +903,11 @@ export class BinaryTree<K = any, V = any, R = any>
1178
903
  * @param [startNode=this._root] - The node to start the search from.
1179
904
  * @param [iterationType=this.iterationType] - The traversal method.
1180
905
  * @returns An array of matching nodes.
1181
-
1182
-
1183
-
1184
-
1185
-
1186
-
1187
-
1188
-
1189
-
1190
-
1191
-
1192
-
1193
-
1194
-
1195
-
1196
-
1197
-
1198
-
1199
-
1200
-
1201
-
1202
-
1203
-
1204
-
1205
-
1206
-
1207
-
1208
-
1209
-
1210
-
1211
-
1212
-
1213
-
1214
-
1215
-
1216
-
1217
- * @example
1218
- * // Get nodes by condition
1219
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1220
- * const nodes = tree.getNodes(node => node.key > 3);
1221
- * console.log(nodes.length); // 2;
906
+ * @example
907
+ * // Get nodes by condition
908
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
909
+ * const nodes = tree.getNodes(node => node.key > 3);
910
+ * console.log(nodes.length); // 2;
1222
911
  */
1223
912
  getNodes(
1224
913
  keyNodeEntryOrPredicate:
@@ -1256,47 +945,13 @@ export class BinaryTree<K = any, V = any, R = any>
1256
945
  * @param [startNode=this._root] - The node to start the search from.
1257
946
  * @param [iterationType=this.iterationType] - The traversal method.
1258
947
  * @returns The first matching node, or undefined if not found.
1259
-
1260
-
1261
-
1262
-
1263
-
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
-
1273
-
1274
-
1275
-
1276
-
1277
-
1278
-
1279
-
1280
-
1281
-
1282
-
1283
-
1284
-
1285
-
1286
-
1287
-
1288
-
1289
-
1290
-
1291
-
1292
-
1293
-
1294
-
1295
-
1296
- * @example
1297
- * // Get node by key
1298
- * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
1299
- * console.log(tree.getNode(2)?.value); // 'child';
948
+ * @example
949
+ * // Get node by key
950
+ * const tree = new BinaryTree<number, string>([
951
+ * [1, 'root'],
952
+ * [2, 'child']
953
+ * ]);
954
+ * console.log(tree.getNode(2)?.value); // 'child';
1300
955
  */
1301
956
  getNode(
1302
957
  keyNodeEntryOrPredicate:
@@ -1327,50 +982,15 @@ export class BinaryTree<K = any, V = any, R = any>
1327
982
  * @param [startNode=this._root] - The node to start searching from (if not in Map mode).
1328
983
  * @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
1329
984
  * @returns The associated value, or undefined.
1330
-
1331
-
1332
-
1333
-
1334
-
1335
-
1336
-
1337
-
1338
-
1339
-
1340
-
1341
-
1342
-
1343
-
1344
-
1345
-
1346
-
1347
-
1348
-
1349
-
1350
-
1351
-
1352
-
1353
-
1354
-
1355
-
1356
-
1357
-
1358
-
1359
-
1360
-
1361
-
1362
-
1363
-
1364
-
1365
-
1366
-
1367
-
1368
-
1369
- * @example
1370
- * // Retrieve value by key
1371
- * const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
1372
- * console.log(tree.get(2)); // 'left';
1373
- * console.log(tree.get(99)); // undefined;
985
+ * @example
986
+ * // Retrieve value by key
987
+ * const tree = new BinaryTree<number, string>([
988
+ * [1, 'root'],
989
+ * [2, 'left'],
990
+ * [3, 'right']
991
+ * ]);
992
+ * console.log(tree.get(2)); // 'left';
993
+ * console.log(tree.get(99)); // undefined;
1374
994
  */
1375
995
  override get(
1376
996
  keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1393,73 +1013,34 @@ export class BinaryTree<K = any, V = any, R = any>
1393
1013
  * @param [startNode] - The node to start the search from.
1394
1014
  * @param [iterationType] - The traversal method.
1395
1015
  * @returns True if a matching node exists, false otherwise.
1396
-
1397
-
1398
-
1399
-
1400
-
1401
-
1402
-
1403
-
1404
-
1405
-
1406
-
1407
-
1408
-
1409
-
1410
-
1411
-
1412
-
1413
-
1414
-
1415
-
1416
-
1417
-
1418
-
1419
-
1420
-
1421
-
1422
-
1423
-
1424
-
1425
-
1426
-
1427
-
1428
-
1429
-
1430
-
1431
-
1432
-
1433
-
1434
-
1435
- * @example
1436
- * // BinaryTree get and has operations
1437
- * const tree = new BinaryTree(
1438
- * [
1439
- * [5, 'five'],
1440
- * [3, 'three'],
1441
- * [7, 'seven'],
1442
- * [1, 'one'],
1443
- * [4, 'four'],
1444
- * [6, 'six'],
1445
- * [8, 'eight']
1446
- * ],
1447
- * { isMapMode: false }
1448
- * );
1449
- *
1450
- * // Check if key exists
1451
- * console.log(tree.has(5)); // true;
1452
- * console.log(tree.has(10)); // false;
1453
- *
1454
- * // Get value by key
1455
- * console.log(tree.get(3)); // 'three';
1456
- * console.log(tree.get(7)); // 'seven';
1457
- * console.log(tree.get(100)); // undefined;
1458
- *
1459
- * // Get node structure
1460
- * const node = tree.getNode(5);
1461
- * console.log(node?.key); // 5;
1462
- * console.log(node?.value); // 'five';
1016
+ * @example
1017
+ * // BinaryTree get and has operations
1018
+ * const tree = new BinaryTree(
1019
+ * [
1020
+ * [5, 'five'],
1021
+ * [3, 'three'],
1022
+ * [7, 'seven'],
1023
+ * [1, 'one'],
1024
+ * [4, 'four'],
1025
+ * [6, 'six'],
1026
+ * [8, 'eight']
1027
+ * ],
1028
+ * { isMapMode: false }
1029
+ * );
1030
+ *
1031
+ * // Check if key exists
1032
+ * console.log(tree.has(5)); // true;
1033
+ * console.log(tree.has(10)); // false;
1034
+ *
1035
+ * // Get value by key
1036
+ * console.log(tree.get(3)); // 'three';
1037
+ * console.log(tree.get(7)); // 'seven';
1038
+ * console.log(tree.get(100)); // undefined;
1039
+ *
1040
+ * // Get node structure
1041
+ * const node = tree.getNode(5);
1042
+ * console.log(node?.key); // 5;
1043
+ * console.log(node?.value); // 'five';
1463
1044
  */
1464
1045
  override has(
1465
1046
  keyNodeEntryOrPredicate?:
@@ -1497,48 +1078,11 @@ export class BinaryTree<K = any, V = any, R = any>
1497
1078
  /**
1498
1079
  * Clears the tree of all nodes and values.
1499
1080
  * @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
1500
-
1501
-
1502
-
1503
-
1504
-
1505
-
1506
-
1507
-
1508
-
1509
-
1510
-
1511
-
1512
-
1513
-
1514
-
1515
-
1516
-
1517
-
1518
-
1519
-
1520
-
1521
-
1522
-
1523
-
1524
-
1525
-
1526
-
1527
-
1528
-
1529
-
1530
-
1531
-
1532
-
1533
-
1534
-
1535
-
1536
-
1537
- * @example
1538
- * // Remove all nodes
1539
- * const tree = new BinaryTree<number>([1, 2, 3]);
1540
- * tree.clear();
1541
- * console.log(tree.isEmpty()); // true;
1081
+ * @example
1082
+ * // Remove all nodes
1083
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1084
+ * tree.clear();
1085
+ * console.log(tree.isEmpty()); // true;
1542
1086
  */
1543
1087
  clear() {
1544
1088
  this._clearNodes();
@@ -1550,46 +1094,9 @@ export class BinaryTree<K = any, V = any, R = any>
1550
1094
  * @remarks Time O(1), Space O(1)
1551
1095
  *
1552
1096
  * @returns True if the tree has no nodes, false otherwise.
1553
-
1554
-
1555
-
1556
-
1557
-
1558
-
1559
-
1560
-
1561
-
1562
-
1563
-
1564
-
1565
-
1566
-
1567
-
1568
-
1569
-
1570
-
1571
-
1572
-
1573
-
1574
-
1575
-
1576
-
1577
-
1578
-
1579
-
1580
-
1581
-
1582
-
1583
-
1584
-
1585
-
1586
-
1587
-
1588
-
1589
-
1590
- * @example
1591
- * // Check empty
1592
- * console.log(new BinaryTree().isEmpty()); // true;
1097
+ * @example
1098
+ * // Check empty
1099
+ * console.log(new BinaryTree().isEmpty()); // true;
1593
1100
  */
1594
1101
  isEmpty(): boolean {
1595
1102
  return this._size === 0;
@@ -1615,48 +1122,11 @@ export class BinaryTree<K = any, V = any, R = any>
1615
1122
  * @param [startNode=this._root] - The node to start checking from.
1616
1123
  * @param [iterationType=this.iterationType] - The traversal method.
1617
1124
  * @returns True if it's a valid BST, false otherwise.
1618
-
1619
-
1620
-
1621
-
1622
-
1623
-
1624
-
1625
-
1626
-
1627
-
1628
-
1629
-
1630
-
1631
-
1632
-
1633
-
1634
-
1635
-
1636
-
1637
-
1638
-
1639
-
1640
-
1641
-
1642
-
1643
-
1644
-
1645
-
1646
-
1647
-
1648
-
1649
-
1650
-
1651
-
1652
-
1653
-
1654
-
1655
- * @example
1656
- * // Check BST property
1657
- * const tree = new BinaryTree<number>([1, 2, 3]);
1658
- * // BinaryTree doesn't guarantee BST order
1659
- * console.log(typeof tree.isBST()); // 'boolean';
1125
+ * @example
1126
+ * // Check BST property
1127
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1128
+ * // BinaryTree doesn't guarantee BST order
1129
+ * console.log(typeof tree.isBST()); // 'boolean';
1660
1130
  */
1661
1131
  isBST(
1662
1132
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1708,50 +1178,11 @@ export class BinaryTree<K = any, V = any, R = any>
1708
1178
  * @param dist - The node to find the depth of.
1709
1179
  * @param [startNode=this._root] - The node to measure depth from (defaults to root).
1710
1180
  * @returns The depth (0 if `dist` is `startNode`).
1711
-
1712
-
1713
-
1714
-
1715
-
1716
-
1717
-
1718
-
1719
-
1720
-
1721
-
1722
-
1723
-
1724
-
1725
-
1726
-
1727
-
1728
-
1729
-
1730
-
1731
-
1732
-
1733
-
1734
-
1735
-
1736
-
1737
-
1738
-
1739
-
1740
-
1741
-
1742
-
1743
-
1744
-
1745
-
1746
-
1747
-
1748
-
1749
-
1750
- * @example
1751
- * // Get depth of a node
1752
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1753
- * const node = tree.getNode(4);
1754
- * console.log(tree.getDepth(node!)); // 2;
1181
+ * @example
1182
+ * // Get depth of a node
1183
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1184
+ * const node = tree.getNode(4);
1185
+ * console.log(tree.getDepth(node!)); // 2;
1755
1186
  */
1756
1187
  getDepth(
1757
1188
  dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1777,49 +1208,10 @@ export class BinaryTree<K = any, V = any, R = any>
1777
1208
  * @param [startNode=this._root] - The node to start measuring from.
1778
1209
  * @param [iterationType=this.iterationType] - The traversal method.
1779
1210
  * @returns The height ( -1 for an empty tree, 0 for a single-node tree).
1780
-
1781
-
1782
-
1783
-
1784
-
1785
-
1786
-
1787
-
1788
-
1789
-
1790
-
1791
-
1792
-
1793
-
1794
-
1795
-
1796
-
1797
-
1798
-
1799
-
1800
-
1801
-
1802
-
1803
-
1804
-
1805
-
1806
-
1807
-
1808
-
1809
-
1810
-
1811
-
1812
-
1813
-
1814
-
1815
-
1816
-
1817
-
1818
-
1819
- * @example
1820
- * // Get tree height
1821
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1822
- * console.log(tree.getHeight()); // 2;
1211
+ * @example
1212
+ * // Get tree height
1213
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1214
+ * console.log(tree.getHeight()); // 2;
1823
1215
  */
1824
1216
  getHeight(
1825
1217
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -2085,52 +1477,13 @@ export class BinaryTree<K = any, V = any, R = any>
2085
1477
  return y;
2086
1478
  }
2087
1479
 
2088
- /**
1480
+ /**
2089
1481
  * Depth-first search traversal
2090
-
2091
-
2092
-
2093
-
2094
-
2095
-
2096
-
2097
-
2098
-
2099
-
2100
-
2101
-
2102
-
2103
-
2104
-
2105
-
2106
-
2107
-
2108
-
2109
-
2110
-
2111
-
2112
-
2113
-
2114
-
2115
-
2116
-
2117
-
2118
-
2119
-
2120
-
2121
-
2122
-
2123
-
2124
-
2125
-
2126
-
2127
-
2128
-
2129
- * @example
2130
- * // Depth-first search traversal
2131
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
2132
- * const inOrder = tree.dfs(node => node.key, 'IN');
2133
- * console.log(inOrder); // [4, 2, 5, 1, 3];
1482
+ * @example
1483
+ * // Depth-first search traversal
1484
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1485
+ * const inOrder = tree.dfs(node => node.key, 'IN');
1486
+ * console.log(inOrder); // [4, 2, 5, 1, 3];
2134
1487
  */
2135
1488
  dfs(): (K | undefined)[];
2136
1489
 
@@ -2177,74 +1530,35 @@ export class BinaryTree<K = any, V = any, R = any>
2177
1530
  return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
2178
1531
  }
2179
1532
 
2180
- /**
1533
+ /**
2181
1534
  * BinaryTree level-order traversal
2182
-
2183
-
2184
-
2185
-
2186
-
2187
-
2188
-
2189
-
2190
-
2191
-
2192
-
2193
-
2194
-
2195
-
2196
-
2197
-
2198
-
2199
-
2200
-
2201
-
2202
-
2203
-
2204
-
2205
-
2206
-
2207
-
2208
-
2209
-
2210
-
2211
-
2212
-
2213
-
2214
-
2215
-
2216
-
2217
-
2218
-
2219
-
2220
-
2221
- * @example
2222
- * // BinaryTree level-order traversal
2223
- * const tree = new BinaryTree([
2224
- * [1, 'one'],
2225
- * [2, 'two'],
2226
- * [3, 'three'],
2227
- * [4, 'four'],
2228
- * [5, 'five'],
2229
- * [6, 'six'],
2230
- * [7, 'seven']
2231
- * ]);
2232
- *
2233
- * // Binary tree maintains level-order insertion
2234
- * // Complete binary tree structure
2235
- * console.log(tree.size); // 7;
2236
- *
2237
- * // Verify all keys are present
2238
- * console.log(tree.has(1)); // true;
2239
- * console.log(tree.has(4)); // true;
2240
- * console.log(tree.has(7)); // true;
2241
- *
2242
- * // Iterate through tree
2243
- * const keys: number[] = [];
2244
- * for (const [key] of tree) {
2245
- * keys.push(key);
2246
- * }
2247
- * console.log(keys.length); // 7;
1535
+ * @example
1536
+ * // BinaryTree level-order traversal
1537
+ * const tree = new BinaryTree([
1538
+ * [1, 'one'],
1539
+ * [2, 'two'],
1540
+ * [3, 'three'],
1541
+ * [4, 'four'],
1542
+ * [5, 'five'],
1543
+ * [6, 'six'],
1544
+ * [7, 'seven']
1545
+ * ]);
1546
+ *
1547
+ * // Binary tree maintains level-order insertion
1548
+ * // Complete binary tree structure
1549
+ * console.log(tree.size); // 7;
1550
+ *
1551
+ * // Verify all keys are present
1552
+ * console.log(tree.has(1)); // true;
1553
+ * console.log(tree.has(4)); // true;
1554
+ * console.log(tree.has(7)); // true;
1555
+ *
1556
+ * // Iterate through tree
1557
+ * const keys: number[] = [];
1558
+ * for (const [key] of tree) {
1559
+ * keys.push(key);
1560
+ * }
1561
+ * console.log(keys.length); // 7;
2248
1562
  */
2249
1563
  bfs(): (K | undefined)[];
2250
1564
 
@@ -2330,50 +1644,13 @@ export class BinaryTree<K = any, V = any, R = any>
2330
1644
  return ans;
2331
1645
  }
2332
1646
 
2333
- /**
1647
+ /**
2334
1648
  * Get leaf nodes
2335
-
2336
-
2337
-
2338
-
2339
-
2340
-
2341
-
2342
-
2343
-
2344
-
2345
-
2346
-
2347
-
2348
-
2349
-
2350
-
2351
-
2352
-
2353
-
2354
-
2355
-
2356
-
2357
-
2358
-
2359
-
2360
-
2361
-
2362
-
2363
-
2364
-
2365
-
2366
-
2367
-
2368
-
2369
-
2370
-
2371
-
2372
- * @example
2373
- * // Get leaf nodes
2374
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
2375
- * const leafKeys = tree.leaves(node => node.key);
2376
- * console.log(leafKeys.length); // > 0;
1649
+ * @example
1650
+ * // Get leaf nodes
1651
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1652
+ * const leafKeys = tree.leaves(node => node.key);
1653
+ * console.log(leafKeys.length); // > 0;
2377
1654
  */
2378
1655
  leaves(): (K | undefined)[];
2379
1656
 
@@ -2435,50 +1712,14 @@ export class BinaryTree<K = any, V = any, R = any>
2435
1712
  return leaves;
2436
1713
  }
2437
1714
 
2438
- /**
1715
+ /**
2439
1716
  * Level-order grouping
2440
-
2441
-
2442
-
2443
-
2444
-
2445
-
2446
-
2447
-
2448
-
2449
-
2450
-
2451
-
2452
-
2453
-
2454
-
2455
-
2456
-
2457
-
2458
-
2459
-
2460
-
2461
-
2462
-
2463
-
2464
-
2465
-
2466
-
2467
-
2468
-
2469
-
2470
-
2471
-
2472
-
2473
-
2474
-
2475
-
2476
- * @example
2477
- * // Level-order grouping
2478
- * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
2479
- * const levels = tree.listLevels(node => node.key);
2480
- * console.log(levels[0]); // [1];
2481
- * console.log(levels[1].sort()); // [2, 3];
1717
+ * @example
1718
+ * // Level-order grouping
1719
+ * const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
1720
+ * const levels = tree.listLevels(node => node.key);
1721
+ * console.log(levels[0]); // [1];
1722
+ * console.log(levels[1].sort()); // [2, 3];
2482
1723
  */
2483
1724
  listLevels(): (K | undefined)[][];
2484
1725
 
@@ -2557,49 +1798,13 @@ export class BinaryTree<K = any, V = any, R = any>
2557
1798
  return levelsNodes;
2558
1799
  }
2559
1800
 
2560
- /**
1801
+ /**
2561
1802
  * Morris traversal (O(1) space)
2562
-
2563
-
2564
-
2565
-
2566
-
2567
-
2568
-
2569
-
2570
-
2571
-
2572
-
2573
-
2574
-
2575
-
2576
-
2577
-
2578
-
2579
-
2580
-
2581
-
2582
-
2583
-
2584
-
2585
-
2586
-
2587
-
2588
-
2589
-
2590
-
2591
-
2592
-
2593
-
2594
-
2595
-
2596
-
2597
-
2598
- * @example
2599
- * // Morris traversal (O(1) space)
2600
- * const tree = new BinaryTree<number>([1, 2, 3]);
2601
- * const result = tree.morris(node => node.key, 'IN');
2602
- * console.log(result.length); // 3;
1803
+ * @example
1804
+ * // Morris traversal (O(1) space)
1805
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1806
+ * const result = tree.morris(node => node.key, 'IN');
1807
+ * console.log(result.length); // 3;
2603
1808
  */
2604
1809
  morris(): (K | undefined)[];
2605
1810
 
@@ -2724,49 +1929,12 @@ export class BinaryTree<K = any, V = any, R = any>
2724
1929
  * @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.
2725
1930
  *
2726
1931
  * @returns A new, cloned instance of the tree.
2727
-
2728
-
2729
-
2730
-
2731
-
2732
-
2733
-
2734
-
2735
-
2736
-
2737
-
2738
-
2739
-
2740
-
2741
-
2742
-
2743
-
2744
-
2745
-
2746
-
2747
-
2748
-
2749
-
2750
-
2751
-
2752
-
2753
-
2754
-
2755
-
2756
-
2757
-
2758
-
2759
-
2760
-
2761
-
2762
-
2763
-
2764
- * @example
2765
- * // Deep copy
2766
- * const tree = new BinaryTree<number>([1, 2, 3]);
2767
- * const copy = tree.clone();
2768
- * copy.delete(1);
2769
- * console.log(tree.has(1)); // true;
1932
+ * @example
1933
+ * // Deep copy
1934
+ * const tree = new BinaryTree<number>([1, 2, 3]);
1935
+ * const copy = tree.clone();
1936
+ * copy.delete(1);
1937
+ * console.log(tree.has(1)); // true;
2770
1938
  */
2771
1939
  clone(): this {
2772
1940
  const out = this._createInstance<K, V, R>();
@@ -2781,48 +1949,11 @@ export class BinaryTree<K = any, V = any, R = any>
2781
1949
  * @param predicate - A function to test each [key, value] pair.
2782
1950
  * @param [thisArg] - `this` context for the predicate.
2783
1951
  * @returns A new, filtered tree.
2784
-
2785
-
2786
-
2787
-
2788
-
2789
-
2790
-
2791
-
2792
-
2793
-
2794
-
2795
-
2796
-
2797
-
2798
-
2799
-
2800
-
2801
-
2802
-
2803
-
2804
-
2805
-
2806
-
2807
-
2808
-
2809
-
2810
-
2811
-
2812
-
2813
-
2814
-
2815
-
2816
-
2817
-
2818
-
2819
-
2820
-
2821
- * @example
2822
- * // Filter nodes by condition
2823
- * const tree = new BinaryTree<number>([1, 2, 3, 4]);
2824
- * const result = tree.filter((_, key) => key > 2);
2825
- * console.log(result.size); // 2;
1952
+ * @example
1953
+ * // Filter nodes by condition
1954
+ * const tree = new BinaryTree<number>([1, 2, 3, 4]);
1955
+ * const result = tree.filter((_, key) => key > 2);
1956
+ * console.log(result.size); // 2;
2826
1957
  */
2827
1958
  filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
2828
1959
  const out = this._createInstance<K, V, R>();
@@ -2842,48 +1973,14 @@ export class BinaryTree<K = any, V = any, R = any>
2842
1973
  * @param [options] - Options for the new tree.
2843
1974
  * @param [thisArg] - `this` context for the callback.
2844
1975
  * @returns A new, mapped tree.
2845
-
2846
-
2847
-
2848
-
2849
-
2850
-
2851
-
2852
-
2853
-
2854
-
2855
-
2856
-
2857
-
2858
-
2859
-
2860
-
2861
-
2862
-
2863
-
2864
-
2865
-
2866
-
2867
-
2868
-
2869
-
2870
-
2871
-
2872
-
2873
-
2874
-
2875
-
2876
-
2877
-
2878
-
2879
-
2880
-
2881
-
2882
- * @example
2883
- * // Transform to new tree
2884
- * const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
2885
- * const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
2886
- * console.log([...mapped.values()]); // contains 11;
1976
+ * @example
1977
+ * // Transform to new tree
1978
+ * const tree = new BinaryTree<number, number>([
1979
+ * [1, 10],
1980
+ * [2, 20]
1981
+ * ]);
1982
+ * const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
1983
+ * console.log([...mapped.values()]); // contains 11;
2887
1984
  */
2888
1985
  map<MK = K, MV = V, MR = any>(
2889
1986
  cb: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -2936,47 +2033,10 @@ export class BinaryTree<K = any, V = any, R = any>
2936
2033
  *
2937
2034
  * @param [options] - Options to control the output.
2938
2035
  * @param [startNode=this._root] - The node to start printing from.
2939
-
2940
-
2941
-
2942
-
2943
-
2944
-
2945
-
2946
-
2947
-
2948
-
2949
-
2950
-
2951
-
2952
-
2953
-
2954
-
2955
-
2956
-
2957
-
2958
-
2959
-
2960
-
2961
-
2962
-
2963
-
2964
-
2965
-
2966
-
2967
-
2968
-
2969
-
2970
-
2971
-
2972
-
2973
-
2974
-
2975
-
2976
- * @example
2977
- * // Display tree
2978
- * const tree = new BinaryTree<number>([1, 2, 3]);
2979
- * expect(() => tree.print()).not.toThrow();
2036
+ * @example
2037
+ * // Display tree
2038
+ * const tree = new BinaryTree<number>([1, 2, 3]);
2039
+ * expect(() => tree.print()).not.toThrow();
2980
2040
  */
2981
2041
  override print(
2982
2042
  options?: BinaryTreePrintOptions,
@@ -2985,6 +2045,67 @@ export class BinaryTree<K = any, V = any, R = any>
2985
2045
  console.log(this.toVisual(startNode, options));
2986
2046
  }
2987
2047
 
2048
+ /**
2049
+ * Deletes a node from the tree (internal, returns balancing metadata).
2050
+ * @remarks Time O(N) — O(N) to find the node + O(H) for predecessor swap. Space O(1). BST/Red-Black Tree/AVL Tree subclasses override to O(log N).
2051
+ * @internal Used by AVL/BST subclasses that need balancing metadata after deletion.
2052
+ *
2053
+ * @param keyNodeEntryRawOrPredicate - The node to delete.
2054
+ * @returns An array containing deletion results with balancing metadata.
2055
+ */
2056
+ protected _deleteInternal(
2057
+ keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
2058
+ ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
2059
+ const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
2060
+ if (!this._root) return deletedResult;
2061
+
2062
+ const curr = this.getNode(keyNodeEntryRawOrPredicate);
2063
+ if (!curr) return deletedResult;
2064
+
2065
+ const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;
2066
+ let needBalanced: BinaryTreeNode<K, V> | undefined;
2067
+ let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;
2068
+
2069
+ if (!curr.left && !curr.right && !parent) {
2070
+ this._setRoot(undefined);
2071
+ } else if (curr.left) {
2072
+ const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
2073
+ if (leftSubTreeRightMost) {
2074
+ const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
2075
+ orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
2076
+
2077
+ if (this._isMapMode) {
2078
+ this._store.set(curr.key, curr);
2079
+ this._store.set(leftSubTreeRightMost.key, leftSubTreeRightMost);
2080
+ }
2081
+
2082
+ if (parentOfLeftSubTreeMax) {
2083
+ if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
2084
+ parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
2085
+ else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
2086
+ needBalanced = parentOfLeftSubTreeMax;
2087
+ }
2088
+ }
2089
+ } else if (parent) {
2090
+ const { familyPosition: fp } = curr;
2091
+ if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
2092
+ parent.left = curr.right;
2093
+ } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {
2094
+ parent.right = curr.right;
2095
+ }
2096
+ needBalanced = parent;
2097
+ } else {
2098
+ this._setRoot(curr.right);
2099
+ curr.right = undefined;
2100
+ }
2101
+
2102
+ this._size = this._size - 1;
2103
+
2104
+ deletedResult.push({ deleted: orgCurrent, needBalanced });
2105
+ if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);
2106
+ return deletedResult;
2107
+ }
2108
+
2988
2109
  protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
2989
2110
  callback: C,
2990
2111
  pattern?: DFSOrderPattern,
@@ -3174,8 +2295,9 @@ export class BinaryTree<K = any, V = any, R = any>
3174
2295
  * @param node - The node.
3175
2296
  * @returns The node's key or undefined.
3176
2297
  */
3177
- protected readonly _DEFAULT_NODE_CALLBACK: NodeCallback<BinaryTreeNode<K, V> | null | undefined, K | undefined> =
3178
- (node): K | undefined => node?.key;
2298
+ protected readonly _DEFAULT_NODE_CALLBACK: NodeCallback<BinaryTreeNode<K, V> | null | undefined, K | undefined> = (
2299
+ node
2300
+ ): K | undefined => node?.key;
3179
2301
 
3180
2302
  /**
3181
2303
  * (Protected) Snapshots the current tree's configuration options.
@@ -3307,14 +2429,20 @@ export class BinaryTree<K = any, V = any, R = any>
3307
2429
  };
3308
2430
 
3309
2431
  const newFrame = (n: BinaryTreeNode<K, V> | null | undefined): Frame => ({
3310
- node: n, stage: 0, leftLayout: emptyDisplayLayout, rightLayout: emptyDisplayLayout
2432
+ node: n,
2433
+ stage: 0,
2434
+ leftLayout: emptyDisplayLayout,
2435
+ rightLayout: emptyDisplayLayout
3311
2436
  });
3312
2437
 
3313
2438
  const stack: Frame[] = [newFrame(node)];
3314
2439
  let result: NodeDisplayLayout = emptyDisplayLayout;
3315
2440
 
3316
2441
  const setChildResult = (layout: NodeDisplayLayout) => {
3317
- if (stack.length === 0) { result = layout; return; }
2442
+ if (stack.length === 0) {
2443
+ result = layout;
2444
+ return;
2445
+ }
3318
2446
  const parent = stack[stack.length - 1];
3319
2447
  if (parent.stage === 1) parent.leftLayout = layout;
3320
2448
  else parent.rightLayout = layout;
@@ -3348,48 +2476,10 @@ export class BinaryTree<K = any, V = any, R = any>
3348
2476
  return result;
3349
2477
  }
3350
2478
 
3351
- protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
3352
- const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
3353
- const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
3354
- const firstLine =
3355
- ' '.repeat(Math.max(0, leftMiddle + 1)) +
3356
- '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +
3357
- line +
3358
- '_'.repeat(Math.max(0, rightMiddle)) +
3359
- ' '.repeat(Math.max(0, rightWidth - rightMiddle));
3360
-
3361
- const secondLine =
3362
- (leftHeight > 0
3363
- ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1)
3364
- : ' '.repeat(leftWidth)) +
3365
- ' '.repeat(width) +
3366
- (rightHeight > 0
3367
- ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1)
3368
- : ' '.repeat(rightWidth));
3369
-
3370
- const mergedLines = [firstLine, secondLine];
3371
-
3372
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
3373
- const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
3374
- const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
3375
- mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
3376
- }
3377
-
3378
- return <NodeDisplayLayout>[
3379
- mergedLines,
3380
- leftWidth + width + rightWidth,
3381
- Math.max(leftHeight, rightHeight) + 2,
3382
- leftWidth + Math.floor(width / 2)
3383
- ];
3384
- }
3385
-
3386
2479
  /**
3387
2480
  * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
3388
2481
  */
3389
- protected _isDisplayLeaf(
3390
- node: BinaryTreeNode<K, V> | null | undefined,
3391
- options: BinaryTreePrintOptions
3392
- ): boolean {
2482
+ protected _isDisplayLeaf(node: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions): boolean {
3393
2483
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
3394
2484
  // Empty/hidden nodes are always leaves
3395
2485
  if (node === null && !isShowNull) return true;