data-structure-typed 2.6.0 → 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.
- package/.github/workflows/ci.yml +7 -2
- package/.github/workflows/release-package.yml +9 -2
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
- package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
- package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
- package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +23 -23
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
- package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
- package/package.json +45 -46
- package/src/common/error.ts +15 -32
- package/src/common/index.ts +0 -3
- package/src/data-structures/base/iterable-element-base.ts +0 -3
- package/src/data-structures/base/linear-base.ts +2 -36
- package/src/data-structures/binary-tree/avl-tree.ts +31 -529
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -572
- package/src/data-structures/binary-tree/binary-tree.ts +326 -1311
- package/src/data-structures/binary-tree/bst.ts +158 -1082
- package/src/data-structures/binary-tree/red-black-tree.ts +451 -1290
- package/src/data-structures/binary-tree/segment-tree.ts +73 -351
- package/src/data-structures/binary-tree/tree-map.ts +462 -5124
- package/src/data-structures/binary-tree/tree-multi-map.ts +302 -4914
- package/src/data-structures/binary-tree/tree-multi-set.ts +284 -3972
- package/src/data-structures/binary-tree/tree-set.ts +338 -4836
- package/src/data-structures/graph/abstract-graph.ts +98 -167
- package/src/data-structures/graph/directed-graph.ts +137 -562
- package/src/data-structures/graph/map-graph.ts +0 -3
- package/src/data-structures/graph/undirected-graph.ts +132 -511
- package/src/data-structures/hash/hash-map.ts +154 -582
- package/src/data-structures/heap/heap.ts +200 -795
- package/src/data-structures/linked-list/doubly-linked-list.ts +121 -865
- package/src/data-structures/linked-list/singly-linked-list.ts +122 -794
- package/src/data-structures/linked-list/skip-linked-list.ts +211 -918
- package/src/data-structures/matrix/matrix.ts +179 -518
- package/src/data-structures/matrix/navigator.ts +0 -1
- package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
- package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
- package/src/data-structures/priority-queue/priority-queue.ts +1 -2
- package/src/data-structures/queue/deque.ts +214 -882
- package/src/data-structures/queue/queue.ts +102 -625
- package/src/data-structures/stack/stack.ts +76 -505
- package/src/data-structures/trie/trie.ts +98 -628
- package/src/types/common.ts +0 -10
- package/src/types/data-structures/binary-tree/bst.ts +0 -7
- package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
- package/src/types/data-structures/graph/abstract-graph.ts +0 -2
- package/src/types/data-structures/hash/hash-map.ts +0 -3
- package/src/types/data-structures/hash/index.ts +0 -1
- package/src/types/data-structures/matrix/navigator.ts +0 -2
- package/src/types/utils/utils.ts +0 -7
- package/src/types/utils/validate-type.ts +0 -7
- package/src/utils/number.ts +0 -2
- package/src/utils/utils.ts +0 -5
|
@@ -10,7 +10,8 @@ import type {
|
|
|
10
10
|
BinaryTreeDeleteResult,
|
|
11
11
|
BinaryTreeOptions,
|
|
12
12
|
BinaryTreePrintOptions,
|
|
13
|
-
BTNEntry,
|
|
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
|
-
|
|
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,55 +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
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
* @example
|
|
607
|
-
* // Add a single node
|
|
608
|
-
* const tree = new BinaryTree<number>();
|
|
609
|
-
* tree.add(1);
|
|
610
|
-
* tree.add(2);
|
|
611
|
-
* tree.add(3);
|
|
612
|
-
* console.log(tree.size); // 3;
|
|
613
|
-
* console.log(tree.has(1)); // true;
|
|
614
|
-
*/
|
|
615
|
-
add(
|
|
616
|
-
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
617
|
-
): 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 {
|
|
618
610
|
return this.set(keyNodeOrEntry);
|
|
619
611
|
}
|
|
620
612
|
|
|
@@ -625,77 +617,34 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
625
617
|
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
626
618
|
* @param [value] - The value, if providing just a key.
|
|
627
619
|
* @returns True if the addition was successful, false otherwise.
|
|
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
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
* @example
|
|
671
|
-
* // basic BinaryTree creation and insertion
|
|
672
|
-
* // Create a BinaryTree with entries
|
|
673
|
-
* const entries: [number, string][] = [
|
|
674
|
-
* [6, 'six'],
|
|
675
|
-
* [1, 'one'],
|
|
676
|
-
* [2, 'two'],
|
|
677
|
-
* [7, 'seven'],
|
|
678
|
-
* [5, 'five'],
|
|
679
|
-
* [3, 'three'],
|
|
680
|
-
* [4, 'four'],
|
|
681
|
-
* [9, 'nine'],
|
|
682
|
-
* [8, 'eight']
|
|
683
|
-
* ];
|
|
684
|
-
*
|
|
685
|
-
* const tree = new BinaryTree(entries);
|
|
686
|
-
*
|
|
687
|
-
* // Verify size
|
|
688
|
-
* console.log(tree.size); // 9;
|
|
689
|
-
*
|
|
690
|
-
* // Add new element
|
|
691
|
-
* tree.set(10, 'ten');
|
|
692
|
-
* 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;
|
|
693
643
|
*/
|
|
694
644
|
set(
|
|
695
645
|
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
696
646
|
value?: V
|
|
697
647
|
): boolean {
|
|
698
|
-
|
|
699
648
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
700
649
|
if (newNode === undefined) return false;
|
|
701
650
|
|
|
@@ -753,51 +702,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
753
702
|
*
|
|
754
703
|
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
755
704
|
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
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
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
* @example
|
|
797
|
-
* // Bulk add
|
|
798
|
-
* const tree = new BinaryTree<number>();
|
|
799
|
-
* tree.addMany([1, 2, 3, 4, 5]);
|
|
800
|
-
* 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;
|
|
801
710
|
*/
|
|
802
711
|
addMany(
|
|
803
712
|
keysNodesEntriesOrRaws: Iterable<
|
|
@@ -814,44 +723,15 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
814
723
|
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
815
724
|
* @param [values] - An optional parallel iterable of values.
|
|
816
725
|
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
* @example
|
|
851
|
-
* // Set multiple entries
|
|
852
|
-
* const tree = new BinaryTree<number, string>();
|
|
853
|
-
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
854
|
-
* 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;
|
|
855
735
|
*/
|
|
856
736
|
setMany(
|
|
857
737
|
keysNodesEntriesOrRaws: Iterable<
|
|
@@ -887,172 +767,29 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
887
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`).
|
|
888
768
|
*
|
|
889
769
|
* @param anotherTree - The tree to merge.
|
|
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
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
* @example
|
|
931
|
-
* // Combine trees
|
|
932
|
-
* const t1 = new BinaryTree<number>([1, 2]);
|
|
933
|
-
* const t2 = new BinaryTree<number>([3, 4]);
|
|
934
|
-
* t1.merge(t2);
|
|
935
|
-
* 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;
|
|
936
776
|
*/
|
|
937
777
|
merge(anotherTree: BinaryTree<K, V, R>) {
|
|
938
778
|
this.setMany(anotherTree, []);
|
|
939
779
|
}
|
|
940
780
|
|
|
941
|
-
/**
|
|
942
|
-
* Deletes a node from the tree (internal, returns balancing metadata).
|
|
943
|
-
* @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).
|
|
944
|
-
* @internal Used by AVL/BST subclasses that need balancing metadata after deletion.
|
|
945
|
-
*
|
|
946
|
-
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
947
|
-
* @returns An array containing deletion results with balancing metadata.
|
|
948
|
-
*/
|
|
949
|
-
protected _deleteInternal(
|
|
950
|
-
keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
|
|
951
|
-
): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
|
|
952
|
-
const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
|
|
953
|
-
if (!this._root) return deletedResult;
|
|
954
|
-
|
|
955
|
-
const curr = this.getNode(keyNodeEntryRawOrPredicate);
|
|
956
|
-
if (!curr) return deletedResult;
|
|
957
|
-
|
|
958
|
-
const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;
|
|
959
|
-
let needBalanced: BinaryTreeNode<K, V> | undefined;
|
|
960
|
-
let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;
|
|
961
|
-
|
|
962
|
-
if (!curr.left && !curr.right && !parent) {
|
|
963
|
-
this._setRoot(undefined);
|
|
964
|
-
} else if (curr.left) {
|
|
965
|
-
const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
|
|
966
|
-
if (leftSubTreeRightMost) {
|
|
967
|
-
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
|
968
|
-
orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
|
|
969
|
-
|
|
970
|
-
if (this._isMapMode) {
|
|
971
|
-
this._store.set(curr.key, curr);
|
|
972
|
-
this._store.set(leftSubTreeRightMost.key, leftSubTreeRightMost);
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
if (parentOfLeftSubTreeMax) {
|
|
976
|
-
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
|
977
|
-
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
|
978
|
-
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
|
|
979
|
-
needBalanced = parentOfLeftSubTreeMax;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
} else if (parent) {
|
|
983
|
-
const { familyPosition: fp } = curr;
|
|
984
|
-
if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
|
|
985
|
-
parent.left = curr.right;
|
|
986
|
-
} else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {
|
|
987
|
-
parent.right = curr.right;
|
|
988
|
-
}
|
|
989
|
-
needBalanced = parent;
|
|
990
|
-
} else {
|
|
991
|
-
this._setRoot(curr.right);
|
|
992
|
-
curr.right = undefined;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
this._size = this._size - 1;
|
|
996
|
-
|
|
997
|
-
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
998
|
-
if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);
|
|
999
|
-
return deletedResult;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
781
|
/**
|
|
1003
782
|
* Deletes a node from the tree.
|
|
1004
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).
|
|
1005
784
|
*
|
|
1006
785
|
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1007
786
|
* @returns True if the node was found and deleted, false otherwise.
|
|
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
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
* @example
|
|
1051
|
-
* // Remove a node
|
|
1052
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1053
|
-
* tree.delete(3);
|
|
1054
|
-
* console.log(tree.has(3)); // false;
|
|
1055
|
-
* 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;
|
|
1056
793
|
*/
|
|
1057
794
|
delete(
|
|
1058
795
|
keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
|
|
@@ -1060,46 +797,13 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1060
797
|
return this._deleteInternal(keyNodeEntryRawOrPredicate).length > 0;
|
|
1061
798
|
}
|
|
1062
799
|
|
|
1063
|
-
|
|
800
|
+
/**
|
|
1064
801
|
* Search by predicate
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
* @example
|
|
1099
|
-
* // Search by predicate
|
|
1100
|
-
* const tree = new BinaryTree<number>([5, 3, 7, 1, 9]);
|
|
1101
|
-
* const found = tree.search(n => n!.key > 5, true);
|
|
1102
|
-
* 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;
|
|
1103
807
|
*/
|
|
1104
808
|
search(
|
|
1105
809
|
keyNodeEntryOrPredicate:
|
|
@@ -1199,50 +903,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1199
903
|
* @param [startNode=this._root] - The node to start the search from.
|
|
1200
904
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1201
905
|
* @returns An array of matching nodes.
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
* @example
|
|
1242
|
-
* // Get nodes by condition
|
|
1243
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1244
|
-
* const nodes = tree.getNodes(node => node.key > 3);
|
|
1245
|
-
* 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;
|
|
1246
911
|
*/
|
|
1247
912
|
getNodes(
|
|
1248
913
|
keyNodeEntryOrPredicate:
|
|
@@ -1280,50 +945,13 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1280
945
|
* @param [startNode=this._root] - The node to start the search from.
|
|
1281
946
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1282
947
|
* @returns The first matching node, or undefined if not found.
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
* @example
|
|
1324
|
-
* // Get node by key
|
|
1325
|
-
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
1326
|
-
* 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';
|
|
1327
955
|
*/
|
|
1328
956
|
getNode(
|
|
1329
957
|
keyNodeEntryOrPredicate:
|
|
@@ -1354,53 +982,15 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1354
982
|
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
1355
983
|
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
1356
984
|
* @returns The associated value, or undefined.
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
* @example
|
|
1400
|
-
* // Retrieve value by key
|
|
1401
|
-
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
1402
|
-
* console.log(tree.get(2)); // 'left';
|
|
1403
|
-
* 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;
|
|
1404
994
|
*/
|
|
1405
995
|
override get(
|
|
1406
996
|
keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
@@ -1423,76 +1013,34 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1423
1013
|
* @param [startNode] - The node to start the search from.
|
|
1424
1014
|
* @param [iterationType] - The traversal method.
|
|
1425
1015
|
* @returns True if a matching node exists, false otherwise.
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
* @example
|
|
1469
|
-
* // BinaryTree get and has operations
|
|
1470
|
-
* const tree = new BinaryTree(
|
|
1471
|
-
* [
|
|
1472
|
-
* [5, 'five'],
|
|
1473
|
-
* [3, 'three'],
|
|
1474
|
-
* [7, 'seven'],
|
|
1475
|
-
* [1, 'one'],
|
|
1476
|
-
* [4, 'four'],
|
|
1477
|
-
* [6, 'six'],
|
|
1478
|
-
* [8, 'eight']
|
|
1479
|
-
* ],
|
|
1480
|
-
* { isMapMode: false }
|
|
1481
|
-
* );
|
|
1482
|
-
*
|
|
1483
|
-
* // Check if key exists
|
|
1484
|
-
* console.log(tree.has(5)); // true;
|
|
1485
|
-
* console.log(tree.has(10)); // false;
|
|
1486
|
-
*
|
|
1487
|
-
* // Get value by key
|
|
1488
|
-
* console.log(tree.get(3)); // 'three';
|
|
1489
|
-
* console.log(tree.get(7)); // 'seven';
|
|
1490
|
-
* console.log(tree.get(100)); // undefined;
|
|
1491
|
-
*
|
|
1492
|
-
* // Get node structure
|
|
1493
|
-
* const node = tree.getNode(5);
|
|
1494
|
-
* console.log(node?.key); // 5;
|
|
1495
|
-
* 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';
|
|
1496
1044
|
*/
|
|
1497
1045
|
override has(
|
|
1498
1046
|
keyNodeEntryOrPredicate?:
|
|
@@ -1530,51 +1078,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1530
1078
|
/**
|
|
1531
1079
|
* Clears the tree of all nodes and values.
|
|
1532
1080
|
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
* @example
|
|
1574
|
-
* // Remove all nodes
|
|
1575
|
-
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
1576
|
-
* tree.clear();
|
|
1577
|
-
* 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;
|
|
1578
1086
|
*/
|
|
1579
1087
|
clear() {
|
|
1580
1088
|
this._clearNodes();
|
|
@@ -1586,49 +1094,9 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1586
1094
|
* @remarks Time O(1), Space O(1)
|
|
1587
1095
|
*
|
|
1588
1096
|
* @returns True if the tree has no nodes, false otherwise.
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
* @example
|
|
1630
|
-
* // Check empty
|
|
1631
|
-
* console.log(new BinaryTree().isEmpty()); // true;
|
|
1097
|
+
* @example
|
|
1098
|
+
* // Check empty
|
|
1099
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
1632
1100
|
*/
|
|
1633
1101
|
isEmpty(): boolean {
|
|
1634
1102
|
return this._size === 0;
|
|
@@ -1654,51 +1122,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1654
1122
|
* @param [startNode=this._root] - The node to start checking from.
|
|
1655
1123
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1656
1124
|
* @returns True if it's a valid BST, false otherwise.
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
* @example
|
|
1698
|
-
* // Check BST property
|
|
1699
|
-
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
1700
|
-
* // BinaryTree doesn't guarantee BST order
|
|
1701
|
-
* 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';
|
|
1702
1130
|
*/
|
|
1703
1131
|
isBST(
|
|
1704
1132
|
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
@@ -1750,53 +1178,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1750
1178
|
* @param dist - The node to find the depth of.
|
|
1751
1179
|
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
1752
1180
|
* @returns The depth (0 if `dist` is `startNode`).
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
* @example
|
|
1796
|
-
* // Get depth of a node
|
|
1797
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1798
|
-
* const node = tree.getNode(4);
|
|
1799
|
-
* 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;
|
|
1800
1186
|
*/
|
|
1801
1187
|
getDepth(
|
|
1802
1188
|
dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
@@ -1822,52 +1208,10 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1822
1208
|
* @param [startNode=this._root] - The node to start measuring from.
|
|
1823
1209
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1824
1210
|
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
* @example
|
|
1868
|
-
* // Get tree height
|
|
1869
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1870
|
-
* 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;
|
|
1871
1215
|
*/
|
|
1872
1216
|
getHeight(
|
|
1873
1217
|
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
@@ -2133,55 +1477,13 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2133
1477
|
return y;
|
|
2134
1478
|
}
|
|
2135
1479
|
|
|
2136
|
-
|
|
1480
|
+
/**
|
|
2137
1481
|
* Depth-first search traversal
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
* @example
|
|
2181
|
-
* // Depth-first search traversal
|
|
2182
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2183
|
-
* const inOrder = tree.dfs(node => node.key, 'IN');
|
|
2184
|
-
* 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];
|
|
2185
1487
|
*/
|
|
2186
1488
|
dfs(): (K | undefined)[];
|
|
2187
1489
|
|
|
@@ -2228,77 +1530,35 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2228
1530
|
return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
|
|
2229
1531
|
}
|
|
2230
1532
|
|
|
2231
|
-
|
|
1533
|
+
/**
|
|
2232
1534
|
* BinaryTree level-order traversal
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
* @example
|
|
2276
|
-
* // BinaryTree level-order traversal
|
|
2277
|
-
* const tree = new BinaryTree([
|
|
2278
|
-
* [1, 'one'],
|
|
2279
|
-
* [2, 'two'],
|
|
2280
|
-
* [3, 'three'],
|
|
2281
|
-
* [4, 'four'],
|
|
2282
|
-
* [5, 'five'],
|
|
2283
|
-
* [6, 'six'],
|
|
2284
|
-
* [7, 'seven']
|
|
2285
|
-
* ]);
|
|
2286
|
-
*
|
|
2287
|
-
* // Binary tree maintains level-order insertion
|
|
2288
|
-
* // Complete binary tree structure
|
|
2289
|
-
* console.log(tree.size); // 7;
|
|
2290
|
-
*
|
|
2291
|
-
* // Verify all keys are present
|
|
2292
|
-
* console.log(tree.has(1)); // true;
|
|
2293
|
-
* console.log(tree.has(4)); // true;
|
|
2294
|
-
* console.log(tree.has(7)); // true;
|
|
2295
|
-
*
|
|
2296
|
-
* // Iterate through tree
|
|
2297
|
-
* const keys: number[] = [];
|
|
2298
|
-
* for (const [key] of tree) {
|
|
2299
|
-
* keys.push(key);
|
|
2300
|
-
* }
|
|
2301
|
-
* 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;
|
|
2302
1562
|
*/
|
|
2303
1563
|
bfs(): (K | undefined)[];
|
|
2304
1564
|
|
|
@@ -2384,53 +1644,13 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2384
1644
|
return ans;
|
|
2385
1645
|
}
|
|
2386
1646
|
|
|
2387
|
-
|
|
1647
|
+
/**
|
|
2388
1648
|
* Get leaf nodes
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
* @example
|
|
2430
|
-
* // Get leaf nodes
|
|
2431
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2432
|
-
* const leafKeys = tree.leaves(node => node.key);
|
|
2433
|
-
* 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;
|
|
2434
1654
|
*/
|
|
2435
1655
|
leaves(): (K | undefined)[];
|
|
2436
1656
|
|
|
@@ -2492,53 +1712,14 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2492
1712
|
return leaves;
|
|
2493
1713
|
}
|
|
2494
1714
|
|
|
2495
|
-
|
|
1715
|
+
/**
|
|
2496
1716
|
* Level-order grouping
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
* @example
|
|
2537
|
-
* // Level-order grouping
|
|
2538
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2539
|
-
* const levels = tree.listLevels(node => node.key);
|
|
2540
|
-
* console.log(levels[0]); // [1];
|
|
2541
|
-
* 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];
|
|
2542
1723
|
*/
|
|
2543
1724
|
listLevels(): (K | undefined)[][];
|
|
2544
1725
|
|
|
@@ -2617,52 +1798,13 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2617
1798
|
return levelsNodes;
|
|
2618
1799
|
}
|
|
2619
1800
|
|
|
2620
|
-
|
|
1801
|
+
/**
|
|
2621
1802
|
* Morris traversal (O(1) space)
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
* @example
|
|
2662
|
-
* // Morris traversal (O(1) space)
|
|
2663
|
-
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2664
|
-
* const result = tree.morris(node => node.key, 'IN');
|
|
2665
|
-
* 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;
|
|
2666
1808
|
*/
|
|
2667
1809
|
morris(): (K | undefined)[];
|
|
2668
1810
|
|
|
@@ -2787,52 +1929,12 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2787
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.
|
|
2788
1930
|
*
|
|
2789
1931
|
* @returns A new, cloned instance of the tree.
|
|
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
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
* @example
|
|
2831
|
-
* // Deep copy
|
|
2832
|
-
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2833
|
-
* const copy = tree.clone();
|
|
2834
|
-
* copy.delete(1);
|
|
2835
|
-
* 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;
|
|
2836
1938
|
*/
|
|
2837
1939
|
clone(): this {
|
|
2838
1940
|
const out = this._createInstance<K, V, R>();
|
|
@@ -2847,51 +1949,11 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2847
1949
|
* @param predicate - A function to test each [key, value] pair.
|
|
2848
1950
|
* @param [thisArg] - `this` context for the predicate.
|
|
2849
1951
|
* @returns A new, filtered tree.
|
|
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
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
* @example
|
|
2891
|
-
* // Filter nodes by condition
|
|
2892
|
-
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2893
|
-
* const result = tree.filter((_, key) => key > 2);
|
|
2894
|
-
* 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;
|
|
2895
1957
|
*/
|
|
2896
1958
|
filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
|
|
2897
1959
|
const out = this._createInstance<K, V, R>();
|
|
@@ -2911,51 +1973,14 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
2911
1973
|
* @param [options] - Options for the new tree.
|
|
2912
1974
|
* @param [thisArg] - `this` context for the callback.
|
|
2913
1975
|
* @returns A new, mapped tree.
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
* @example
|
|
2955
|
-
* // Transform to new tree
|
|
2956
|
-
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2957
|
-
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2958
|
-
* 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;
|
|
2959
1984
|
*/
|
|
2960
1985
|
map<MK = K, MV = V, MR = any>(
|
|
2961
1986
|
cb: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
@@ -3008,50 +2033,10 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
3008
2033
|
*
|
|
3009
2034
|
* @param [options] - Options to control the output.
|
|
3010
2035
|
* @param [startNode=this._root] - The node to start printing from.
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
* @example
|
|
3052
|
-
* // Display tree
|
|
3053
|
-
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
3054
|
-
* 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();
|
|
3055
2040
|
*/
|
|
3056
2041
|
override print(
|
|
3057
2042
|
options?: BinaryTreePrintOptions,
|
|
@@ -3060,6 +2045,67 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
3060
2045
|
console.log(this.toVisual(startNode, options));
|
|
3061
2046
|
}
|
|
3062
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
|
+
|
|
3063
2109
|
protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
3064
2110
|
callback: C,
|
|
3065
2111
|
pattern?: DFSOrderPattern,
|
|
@@ -3249,8 +2295,9 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
3249
2295
|
* @param node - The node.
|
|
3250
2296
|
* @returns The node's key or undefined.
|
|
3251
2297
|
*/
|
|
3252
|
-
protected readonly _DEFAULT_NODE_CALLBACK: NodeCallback<BinaryTreeNode<K, V> | null | undefined, K | undefined> =
|
|
3253
|
-
|
|
2298
|
+
protected readonly _DEFAULT_NODE_CALLBACK: NodeCallback<BinaryTreeNode<K, V> | null | undefined, K | undefined> = (
|
|
2299
|
+
node
|
|
2300
|
+
): K | undefined => node?.key;
|
|
3254
2301
|
|
|
3255
2302
|
/**
|
|
3256
2303
|
* (Protected) Snapshots the current tree's configuration options.
|
|
@@ -3382,14 +2429,20 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
3382
2429
|
};
|
|
3383
2430
|
|
|
3384
2431
|
const newFrame = (n: BinaryTreeNode<K, V> | null | undefined): Frame => ({
|
|
3385
|
-
node: n,
|
|
2432
|
+
node: n,
|
|
2433
|
+
stage: 0,
|
|
2434
|
+
leftLayout: emptyDisplayLayout,
|
|
2435
|
+
rightLayout: emptyDisplayLayout
|
|
3386
2436
|
});
|
|
3387
2437
|
|
|
3388
2438
|
const stack: Frame[] = [newFrame(node)];
|
|
3389
2439
|
let result: NodeDisplayLayout = emptyDisplayLayout;
|
|
3390
2440
|
|
|
3391
2441
|
const setChildResult = (layout: NodeDisplayLayout) => {
|
|
3392
|
-
if (stack.length === 0) {
|
|
2442
|
+
if (stack.length === 0) {
|
|
2443
|
+
result = layout;
|
|
2444
|
+
return;
|
|
2445
|
+
}
|
|
3393
2446
|
const parent = stack[stack.length - 1];
|
|
3394
2447
|
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3395
2448
|
else parent.rightLayout = layout;
|
|
@@ -3423,48 +2476,10 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
3423
2476
|
return result;
|
|
3424
2477
|
}
|
|
3425
2478
|
|
|
3426
|
-
protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
|
|
3427
|
-
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3428
|
-
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3429
|
-
const firstLine =
|
|
3430
|
-
' '.repeat(Math.max(0, leftMiddle + 1)) +
|
|
3431
|
-
'_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +
|
|
3432
|
-
line +
|
|
3433
|
-
'_'.repeat(Math.max(0, rightMiddle)) +
|
|
3434
|
-
' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
|
3435
|
-
|
|
3436
|
-
const secondLine =
|
|
3437
|
-
(leftHeight > 0
|
|
3438
|
-
? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1)
|
|
3439
|
-
: ' '.repeat(leftWidth)) +
|
|
3440
|
-
' '.repeat(width) +
|
|
3441
|
-
(rightHeight > 0
|
|
3442
|
-
? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1)
|
|
3443
|
-
: ' '.repeat(rightWidth));
|
|
3444
|
-
|
|
3445
|
-
const mergedLines = [firstLine, secondLine];
|
|
3446
|
-
|
|
3447
|
-
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3448
|
-
const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
|
|
3449
|
-
const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
|
|
3450
|
-
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
|
3451
|
-
}
|
|
3452
|
-
|
|
3453
|
-
return <NodeDisplayLayout>[
|
|
3454
|
-
mergedLines,
|
|
3455
|
-
leftWidth + width + rightWidth,
|
|
3456
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
3457
|
-
leftWidth + Math.floor(width / 2)
|
|
3458
|
-
];
|
|
3459
|
-
}
|
|
3460
|
-
|
|
3461
2479
|
/**
|
|
3462
2480
|
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3463
2481
|
*/
|
|
3464
|
-
protected _isDisplayLeaf(
|
|
3465
|
-
node: BinaryTreeNode<K, V> | null | undefined,
|
|
3466
|
-
options: BinaryTreePrintOptions
|
|
3467
|
-
): boolean {
|
|
2482
|
+
protected _isDisplayLeaf(node: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions): boolean {
|
|
3468
2483
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3469
2484
|
// Empty/hidden nodes are always leaves
|
|
3470
2485
|
if (node === null && !isShowNull) return true;
|