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.
- package/.github/workflows/ci.yml +7 -2
- package/.github/workflows/release-package.yml +9 -2
- package/.husky/pre-commit +3 -0
- package/CHANGELOG.md +1 -1
- package/MIGRATION.md +48 -0
- package/README.md +20 -2
- package/README_CN.md +20 -2
- package/SPECIFICATION.md +24 -0
- package/SPECIFICATION.zh-CN.md +24 -0
- package/dist/cjs/binary-tree.cjs +1897 -19
- package/dist/cjs/graph.cjs +174 -0
- package/dist/cjs/hash.cjs +33 -0
- package/dist/cjs/heap.cjs +71 -0
- package/dist/cjs/index.cjs +2383 -3
- package/dist/cjs/linked-list.cjs +224 -2
- package/dist/cjs/matrix.cjs +24 -0
- package/dist/cjs/priority-queue.cjs +71 -0
- package/dist/cjs/queue.cjs +221 -1
- package/dist/cjs/stack.cjs +59 -0
- package/dist/cjs/trie.cjs +62 -0
- package/dist/cjs-legacy/binary-tree.cjs +1897 -19
- package/dist/cjs-legacy/graph.cjs +174 -0
- package/dist/cjs-legacy/hash.cjs +33 -0
- package/dist/cjs-legacy/heap.cjs +71 -0
- package/dist/cjs-legacy/index.cjs +2383 -3
- package/dist/cjs-legacy/linked-list.cjs +224 -2
- package/dist/cjs-legacy/matrix.cjs +24 -0
- package/dist/cjs-legacy/priority-queue.cjs +71 -0
- package/dist/cjs-legacy/queue.cjs +221 -1
- package/dist/cjs-legacy/stack.cjs +59 -0
- package/dist/cjs-legacy/trie.cjs +62 -0
- package/dist/esm/binary-tree.mjs +1897 -19
- package/dist/esm/graph.mjs +174 -0
- package/dist/esm/hash.mjs +33 -0
- package/dist/esm/heap.mjs +71 -0
- package/dist/esm/index.mjs +2383 -3
- package/dist/esm/linked-list.mjs +224 -2
- package/dist/esm/matrix.mjs +24 -0
- package/dist/esm/priority-queue.mjs +71 -0
- package/dist/esm/queue.mjs +221 -1
- package/dist/esm/stack.mjs +59 -0
- package/dist/esm/trie.mjs +62 -0
- package/dist/esm-legacy/binary-tree.mjs +1897 -19
- package/dist/esm-legacy/graph.mjs +174 -0
- package/dist/esm-legacy/hash.mjs +33 -0
- package/dist/esm-legacy/heap.mjs +71 -0
- package/dist/esm-legacy/index.mjs +2383 -3
- package/dist/esm-legacy/linked-list.mjs +224 -2
- package/dist/esm-legacy/matrix.mjs +24 -0
- package/dist/esm-legacy/priority-queue.mjs +71 -0
- package/dist/esm-legacy/queue.mjs +221 -1
- package/dist/esm-legacy/stack.mjs +59 -0
- package/dist/esm-legacy/trie.mjs +62 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +17 -0
- package/dist/types/data-structures/base/linear-base.d.ts +6 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +36 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +75 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +72 -0
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +375 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +389 -0
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +330 -0
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +438 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
- package/dist/types/data-structures/heap/heap.d.ts +42 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -2
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
- package/dist/types/data-structures/queue/deque.d.ts +90 -1
- package/dist/types/data-structures/queue/queue.d.ts +36 -0
- package/dist/types/data-structures/stack/stack.d.ts +30 -0
- package/dist/types/data-structures/trie/trie.d.ts +36 -0
- package/dist/umd/data-structure-typed.js +2383 -3
- package/dist/umd/data-structure-typed.min.js +3 -3
- 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 +30 -26
- 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/jest.integration.config.js +1 -2
- package/package.json +51 -50
- package/src/common/error.ts +15 -32
- package/src/common/index.ts +0 -3
- package/src/data-structures/base/iterable-element-base.ts +32 -3
- package/src/data-structures/base/linear-base.ts +13 -36
- package/src/data-structures/binary-tree/avl-tree.ts +31 -493
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -530
- package/src/data-structures/binary-tree/binary-tree.ts +326 -1236
- package/src/data-structures/binary-tree/bst.ts +158 -1010
- package/src/data-structures/binary-tree/red-black-tree.ts +451 -1233
- package/src/data-structures/binary-tree/segment-tree.ts +73 -333
- package/src/data-structures/binary-tree/tree-map.ts +462 -4749
- package/src/data-structures/binary-tree/tree-multi-map.ts +310 -4530
- package/src/data-structures/binary-tree/tree-multi-set.ts +300 -3652
- package/src/data-structures/binary-tree/tree-set.ts +437 -4443
- package/src/data-structures/graph/abstract-graph.ts +98 -167
- package/src/data-structures/graph/directed-graph.ts +137 -532
- package/src/data-structures/graph/map-graph.ts +0 -3
- package/src/data-structures/graph/undirected-graph.ts +132 -484
- package/src/data-structures/hash/hash-map.ts +154 -549
- package/src/data-structures/heap/heap.ts +200 -753
- package/src/data-structures/linked-list/doubly-linked-list.ts +153 -809
- package/src/data-structures/linked-list/singly-linked-list.ts +122 -749
- package/src/data-structures/linked-list/skip-linked-list.ts +211 -864
- package/src/data-structures/matrix/matrix.ts +179 -494
- 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 +241 -807
- package/src/data-structures/queue/queue.ts +102 -589
- package/src/data-structures/stack/stack.ts +76 -475
- package/src/data-structures/trie/trie.ts +98 -592
- 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,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
|
-
|
|
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,
|
|
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) {
|
|
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;
|