undirected-graph-typed 1.52.4 → 1.52.5
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/dist/data-structures/base/iterable-element-base.d.ts +1 -37
- package/dist/data-structures/base/iterable-element-base.js +1 -37
- package/dist/data-structures/base/iterable-entry-base.d.ts +2 -54
- package/dist/data-structures/base/iterable-entry-base.js +1 -49
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -32
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +9 -41
- package/dist/data-structures/binary-tree/avl-tree.d.ts +0 -46
- package/dist/data-structures/binary-tree/avl-tree.js +0 -46
- package/dist/data-structures/binary-tree/binary-tree.d.ts +82 -147
- package/dist/data-structures/binary-tree/binary-tree.js +299 -331
- package/dist/data-structures/binary-tree/bst.d.ts +1 -40
- package/dist/data-structures/binary-tree/bst.js +12 -44
- package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -48
- package/dist/data-structures/binary-tree/rb-tree.js +2 -50
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +0 -32
- package/dist/data-structures/binary-tree/tree-multi-map.js +9 -41
- package/dist/data-structures/graph/abstract-graph.d.ts +0 -75
- package/dist/data-structures/graph/abstract-graph.js +0 -75
- package/dist/data-structures/graph/directed-graph.d.ts +0 -98
- package/dist/data-structures/graph/directed-graph.js +0 -98
- package/dist/data-structures/graph/undirected-graph.d.ts +0 -50
- package/dist/data-structures/graph/undirected-graph.js +0 -50
- package/dist/data-structures/hash/hash-map.d.ts +5 -92
- package/dist/data-structures/hash/hash-map.js +27 -111
- package/dist/data-structures/heap/heap.d.ts +0 -32
- package/dist/data-structures/heap/heap.js +0 -32
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +5 -88
- package/dist/data-structures/linked-list/doubly-linked-list.js +5 -88
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +1 -83
- package/dist/data-structures/linked-list/singly-linked-list.js +2 -84
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +1 -35
- package/dist/data-structures/linked-list/skip-linked-list.js +1 -35
- package/dist/data-structures/queue/deque.d.ts +1 -98
- package/dist/data-structures/queue/deque.js +3 -99
- package/dist/data-structures/queue/queue.d.ts +1 -54
- package/dist/data-structures/queue/queue.js +0 -53
- package/dist/data-structures/stack/stack.d.ts +1 -34
- package/dist/data-structures/stack/stack.js +1 -34
- package/dist/data-structures/tree/tree.js +2 -1
- package/dist/data-structures/trie/trie.d.ts +0 -64
- package/dist/data-structures/trie/trie.js +0 -64
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +8 -0
- package/dist/types/data-structures/binary-tree/binary-tree.js +6 -0
- package/dist/types/utils/utils.d.ts +13 -12
- package/dist/utils/number.d.ts +13 -0
- package/dist/utils/number.js +13 -0
- package/dist/utils/utils.d.ts +125 -3
- package/dist/utils/utils.js +177 -21
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +2 -42
- package/src/data-structures/base/iterable-entry-base.ts +3 -62
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +8 -48
- package/src/data-structures/binary-tree/avl-tree.ts +0 -57
- package/src/data-structures/binary-tree/binary-tree.ts +329 -358
- package/src/data-structures/binary-tree/bst.ts +11 -54
- package/src/data-structures/binary-tree/rb-tree.ts +2 -62
- package/src/data-structures/binary-tree/tree-multi-map.ts +8 -48
- package/src/data-structures/graph/abstract-graph.ts +0 -92
- package/src/data-structures/graph/directed-graph.ts +0 -122
- package/src/data-structures/graph/undirected-graph.ts +0 -62
- package/src/data-structures/hash/hash-map.ts +29 -133
- package/src/data-structures/heap/heap.ts +0 -40
- package/src/data-structures/linked-list/doubly-linked-list.ts +5 -112
- package/src/data-structures/linked-list/singly-linked-list.ts +2 -104
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -44
- package/src/data-structures/queue/deque.ts +2 -125
- package/src/data-structures/queue/queue.ts +1 -68
- package/src/data-structures/stack/stack.ts +1 -43
- package/src/data-structures/tree/tree.ts +1 -1
- package/src/data-structures/trie/trie.ts +0 -80
- package/src/types/data-structures/binary-tree/binary-tree.ts +8 -1
- package/src/types/utils/utils.ts +17 -15
- package/src/utils/number.ts +13 -0
- package/src/utils/utils.ts +174 -18
|
@@ -22,8 +22,9 @@ import type {
|
|
|
22
22
|
NodeDisplayLayout,
|
|
23
23
|
OptBTNOrNull
|
|
24
24
|
} from '../../types';
|
|
25
|
+
import { DFSOperation, DFSStackItem } from '../../types';
|
|
25
26
|
import { IBinaryTree } from '../../interfaces';
|
|
26
|
-
import { trampoline } from '../../utils';
|
|
27
|
+
import { isComparable, trampoline } from '../../utils';
|
|
27
28
|
import { Queue } from '../queue';
|
|
28
29
|
import { IterableEntryBase } from '../base';
|
|
29
30
|
|
|
@@ -55,7 +56,7 @@ export class BinaryTreeNode<
|
|
|
55
56
|
this.value = value;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
protected _left?: NODE
|
|
59
|
+
protected _left?: OptBTNOrNull<NODE>;
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* The function returns the value of the `_left` property, which can be of type `NODE`, `null`, or
|
|
@@ -79,7 +80,7 @@ export class BinaryTreeNode<
|
|
|
79
80
|
this._left = v;
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
protected _right?: NODE
|
|
83
|
+
protected _right?: OptBTNOrNull<NODE>;
|
|
83
84
|
|
|
84
85
|
/**
|
|
85
86
|
* The function returns the right node of a binary tree or null if it doesn't exist.
|
|
@@ -248,17 +249,17 @@ export class BinaryTree<
|
|
|
248
249
|
|
|
249
250
|
if (this.isNode(keyOrNodeOrEntryOrRawElement)) return keyOrNodeOrEntryOrRawElement;
|
|
250
251
|
|
|
251
|
-
if (this.toEntryFn) {
|
|
252
|
-
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
|
|
253
|
-
if (key) return this.createNode(key, entryValue ?? value);
|
|
254
|
-
else return;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
252
|
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
|
|
258
|
-
const [key,
|
|
253
|
+
const [key, entryValue] = keyOrNodeOrEntryOrRawElement;
|
|
259
254
|
if (key === undefined) return;
|
|
260
255
|
else if (key === null) return null;
|
|
261
|
-
|
|
256
|
+
if (this.isKey(key)) return this.createNode(key, value ?? entryValue);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (this.toEntryFn) {
|
|
260
|
+
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
|
|
261
|
+
if (this.isKey(key)) return this.createNode(key, value ?? entryValue);
|
|
262
|
+
else return;
|
|
262
263
|
}
|
|
263
264
|
|
|
264
265
|
if (this.isKey(keyOrNodeOrEntryOrRawElement)) return this.createNode(keyOrNodeOrEntryOrRawElement, value);
|
|
@@ -266,11 +267,6 @@ export class BinaryTree<
|
|
|
266
267
|
return;
|
|
267
268
|
}
|
|
268
269
|
|
|
269
|
-
/**
|
|
270
|
-
* Time Complexity: O(n)
|
|
271
|
-
* Space Complexity: O(log n)
|
|
272
|
-
*/
|
|
273
|
-
|
|
274
270
|
/**
|
|
275
271
|
* Time Complexity: O(n)
|
|
276
272
|
* Space Complexity: O(log n)
|
|
@@ -287,7 +283,7 @@ export class BinaryTree<
|
|
|
287
283
|
*/
|
|
288
284
|
ensureNode(
|
|
289
285
|
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
290
|
-
iterationType: IterationType =
|
|
286
|
+
iterationType: IterationType = this.iterationType
|
|
291
287
|
): OptBTNOrNull<NODE> {
|
|
292
288
|
if (keyOrNodeOrEntryOrRawElement === null) return null;
|
|
293
289
|
if (keyOrNodeOrEntryOrRawElement === undefined) return;
|
|
@@ -296,7 +292,7 @@ export class BinaryTree<
|
|
|
296
292
|
|
|
297
293
|
if (this.toEntryFn) {
|
|
298
294
|
const [key] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
|
|
299
|
-
if (key) return this.getNodeByKey(key);
|
|
295
|
+
if (this.isKey(key)) return this.getNodeByKey(key);
|
|
300
296
|
}
|
|
301
297
|
|
|
302
298
|
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
|
|
@@ -338,7 +334,7 @@ export class BinaryTree<
|
|
|
338
334
|
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
|
339
335
|
* @returns a boolean value.
|
|
340
336
|
*/
|
|
341
|
-
|
|
337
|
+
isRealNodeOrNull(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
|
|
342
338
|
return this.isRealNode(node) || node === null;
|
|
343
339
|
}
|
|
344
340
|
|
|
@@ -348,10 +344,26 @@ export class BinaryTree<
|
|
|
348
344
|
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
|
349
345
|
* @returns a boolean value.
|
|
350
346
|
*/
|
|
351
|
-
isNIL(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>) {
|
|
347
|
+
isNIL(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): boolean {
|
|
352
348
|
return node === this.NIL;
|
|
353
349
|
}
|
|
354
350
|
|
|
351
|
+
/**
|
|
352
|
+
* The function `isLeaf` determines whether a given node is a leaf node in a binary tree structure.
|
|
353
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} node - The `node` parameter in the `isLeaf` function
|
|
354
|
+
* can be either a regular node (`R`) or a `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
|
355
|
+
* @returns The `isLeaf` function is checking if the provided node is a leaf node in a binary tree.
|
|
356
|
+
* If the node is `undefined`, it returns `false`. If the node is `null`, it returns `true`.
|
|
357
|
+
* Otherwise, it checks if both the left and right children of the node are not real nodes, and
|
|
358
|
+
* returns `true` if they are not, indicating that the node is a
|
|
359
|
+
*/
|
|
360
|
+
isLeaf(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): boolean {
|
|
361
|
+
node = this.ensureNode(node);
|
|
362
|
+
if (node === undefined) return false;
|
|
363
|
+
if (node === null) return true;
|
|
364
|
+
return !this.isRealNode(node.left) && !this.isRealNode(node.right);
|
|
365
|
+
}
|
|
366
|
+
|
|
355
367
|
/**
|
|
356
368
|
* The function checks if the input is an array with two elements, indicating it is a binary tree
|
|
357
369
|
* node entry.
|
|
@@ -366,38 +378,21 @@ export class BinaryTree<
|
|
|
366
378
|
}
|
|
367
379
|
|
|
368
380
|
/**
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
|
|
378
|
-
|
|
381
|
+
* Time Complexity O(1)
|
|
382
|
+
* Space Complexity O(1)
|
|
383
|
+
*
|
|
384
|
+
* The function `isKey` checks if a given key is comparable.
|
|
385
|
+
* @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
|
|
386
|
+
* TypeScript.
|
|
387
|
+
* @returns The function `isKey` is checking if the `key` parameter is `null` or if it is comparable.
|
|
388
|
+
* If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
|
|
389
|
+
* `isComparable` function, which is not provided in the code snippet.
|
|
390
|
+
*/
|
|
391
|
+
isKey(key: any): key is K {
|
|
379
392
|
if (key === null) return true;
|
|
380
|
-
|
|
381
|
-
if (keyType === 'string' || keyType === 'bigint' || keyType === 'boolean') return true;
|
|
382
|
-
if (keyType === 'number') return !isNaN(key);
|
|
383
|
-
if (keyType === 'symbol' || keyType === 'undefined') return false;
|
|
384
|
-
if (keyType === 'function') return this.isKey(key());
|
|
385
|
-
if (keyType === 'object') {
|
|
386
|
-
if (typeof key.toString === 'function') return true;
|
|
387
|
-
if (isCheckValueOf && typeof key.valueOf === 'function') {
|
|
388
|
-
this.isKey(key.valueOf(), false);
|
|
389
|
-
}
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return false;
|
|
393
|
+
return isComparable(key);
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
-
/**
|
|
397
|
-
* Time Complexity O(n)
|
|
398
|
-
* Space Complexity O(1)
|
|
399
|
-
*/
|
|
400
|
-
|
|
401
396
|
/**
|
|
402
397
|
* Time Complexity O(n)
|
|
403
398
|
* Space Complexity O(1)
|
|
@@ -467,12 +462,6 @@ export class BinaryTree<
|
|
|
467
462
|
return false; // If the insertion position cannot be found, return undefined
|
|
468
463
|
}
|
|
469
464
|
|
|
470
|
-
/**
|
|
471
|
-
* Time Complexity: O(k * n)
|
|
472
|
-
* Space Complexity: O(1)
|
|
473
|
-
* Comments: The time complexity for adding a node depends on the depth of the tree. In the best case (when the tree is empty), it's O(1). In the worst case (when the tree is a degenerate tree), it's O(n). The space complexity is constant.
|
|
474
|
-
*/
|
|
475
|
-
|
|
476
465
|
/**
|
|
477
466
|
* Time Complexity: O(k * n)
|
|
478
467
|
* Space Complexity: O(1)
|
|
@@ -515,12 +504,6 @@ export class BinaryTree<
|
|
|
515
504
|
return inserted;
|
|
516
505
|
}
|
|
517
506
|
|
|
518
|
-
/**
|
|
519
|
-
* Time Complexity: O(k * n)
|
|
520
|
-
* Space Complexity: O(1)
|
|
521
|
-
* "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
|
522
|
-
*/
|
|
523
|
-
|
|
524
507
|
/**
|
|
525
508
|
* Time Complexity: O(k * n)
|
|
526
509
|
* Space Complexity: O(1)
|
|
@@ -549,11 +532,6 @@ export class BinaryTree<
|
|
|
549
532
|
|
|
550
533
|
delete<C extends BTNCallback<NODE>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeleteResult<NODE>[];
|
|
551
534
|
|
|
552
|
-
/**
|
|
553
|
-
* Time Complexity: O(n)
|
|
554
|
-
* Space Complexity: O(1)
|
|
555
|
-
*/
|
|
556
|
-
|
|
557
535
|
/**
|
|
558
536
|
* Time Complexity: O(n)
|
|
559
537
|
* Space Complexity: O(1)
|
|
@@ -587,7 +565,7 @@ export class BinaryTree<
|
|
|
587
565
|
if (!curr.left && !curr.right && !parent) {
|
|
588
566
|
this._setRoot(undefined);
|
|
589
567
|
} else if (curr.left) {
|
|
590
|
-
const leftSubTreeRightMost = this.getRightMost(curr.left);
|
|
568
|
+
const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
|
|
591
569
|
if (leftSubTreeRightMost) {
|
|
592
570
|
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
|
593
571
|
orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
|
|
@@ -641,11 +619,6 @@ export class BinaryTree<
|
|
|
641
619
|
iterationType?: IterationType
|
|
642
620
|
): NODE[];
|
|
643
621
|
|
|
644
|
-
/**
|
|
645
|
-
* Time Complexity: O(n)
|
|
646
|
-
* Space Complexity: O(k + log n)
|
|
647
|
-
*/
|
|
648
|
-
|
|
649
622
|
/**
|
|
650
623
|
* Time Complexity: O(n)
|
|
651
624
|
* Space Complexity: O(k + log n)
|
|
@@ -677,6 +650,8 @@ export class BinaryTree<
|
|
|
677
650
|
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
678
651
|
iterationType: IterationType = this.iterationType
|
|
679
652
|
): NODE[] {
|
|
653
|
+
if (identifier === undefined) return [];
|
|
654
|
+
if (identifier === null) return [];
|
|
680
655
|
beginRoot = this.ensureNode(beginRoot);
|
|
681
656
|
if (!beginRoot) return [];
|
|
682
657
|
callback = this._ensureCallback(identifier, callback);
|
|
@@ -734,11 +709,6 @@ export class BinaryTree<
|
|
|
734
709
|
iterationType?: IterationType
|
|
735
710
|
): OptBTNOrNull<NODE>;
|
|
736
711
|
|
|
737
|
-
/**
|
|
738
|
-
* Time Complexity: O(n)
|
|
739
|
-
* Space Complexity: O(log n).
|
|
740
|
-
*/
|
|
741
|
-
|
|
742
712
|
/**
|
|
743
713
|
* Time Complexity: O(n)
|
|
744
714
|
* Space Complexity: O(log n).
|
|
@@ -766,11 +736,6 @@ export class BinaryTree<
|
|
|
766
736
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
767
737
|
}
|
|
768
738
|
|
|
769
|
-
/**
|
|
770
|
-
* Time Complexity: O(n)
|
|
771
|
-
* Space Complexity: O(log n)
|
|
772
|
-
*/
|
|
773
|
-
|
|
774
739
|
/**
|
|
775
740
|
* Time Complexity: O(n)
|
|
776
741
|
* Space Complexity: O(log n)
|
|
@@ -783,7 +748,7 @@ export class BinaryTree<
|
|
|
783
748
|
* It has a default value of `'ITERATIVE'`.
|
|
784
749
|
* @returns a value of type NODE, null, or undefined.
|
|
785
750
|
*/
|
|
786
|
-
getNodeByKey(key: K, iterationType: IterationType =
|
|
751
|
+
getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptBTNOrNull<NODE> {
|
|
787
752
|
return this.getNode(key, this._DEFAULT_CALLBACK, this.root, iterationType);
|
|
788
753
|
}
|
|
789
754
|
|
|
@@ -808,11 +773,6 @@ export class BinaryTree<
|
|
|
808
773
|
iterationType?: IterationType
|
|
809
774
|
): V | undefined;
|
|
810
775
|
|
|
811
|
-
/**
|
|
812
|
-
* Time Complexity: O(n)
|
|
813
|
-
* Space Complexity: O(log n)
|
|
814
|
-
*/
|
|
815
|
-
|
|
816
776
|
/**
|
|
817
777
|
* Time Complexity: O(n)
|
|
818
778
|
* Space Complexity: O(log n)
|
|
@@ -864,11 +824,6 @@ export class BinaryTree<
|
|
|
864
824
|
iterationType?: IterationType
|
|
865
825
|
): boolean;
|
|
866
826
|
|
|
867
|
-
/**
|
|
868
|
-
* Time Complexity: O(n)
|
|
869
|
-
* Space Complexity: O(log n)
|
|
870
|
-
*/
|
|
871
|
-
|
|
872
827
|
/**
|
|
873
828
|
* Time Complexity: O(n)
|
|
874
829
|
* Space Complexity: O(log n)
|
|
@@ -900,11 +855,6 @@ export class BinaryTree<
|
|
|
900
855
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
901
856
|
}
|
|
902
857
|
|
|
903
|
-
/**
|
|
904
|
-
* Time Complexity: O(1)
|
|
905
|
-
* Space Complexity: O(1)
|
|
906
|
-
*/
|
|
907
|
-
|
|
908
858
|
/**
|
|
909
859
|
* Time Complexity: O(1)
|
|
910
860
|
* Space Complexity: O(1)
|
|
@@ -916,11 +866,6 @@ export class BinaryTree<
|
|
|
916
866
|
this._size = 0;
|
|
917
867
|
}
|
|
918
868
|
|
|
919
|
-
/**
|
|
920
|
-
* Time Complexity: O(1)
|
|
921
|
-
* Space Complexity: O(1)
|
|
922
|
-
*/
|
|
923
|
-
|
|
924
869
|
/**
|
|
925
870
|
* Time Complexity: O(1)
|
|
926
871
|
* Space Complexity: O(1)
|
|
@@ -932,11 +877,6 @@ export class BinaryTree<
|
|
|
932
877
|
return this.size === 0;
|
|
933
878
|
}
|
|
934
879
|
|
|
935
|
-
/**
|
|
936
|
-
* Time Complexity: O(n)
|
|
937
|
-
* Space Complexity: O(log n)
|
|
938
|
-
*/
|
|
939
|
-
|
|
940
880
|
/**
|
|
941
881
|
* Time Complexity: O(n)
|
|
942
882
|
* Space Complexity: O(log n)
|
|
@@ -953,11 +893,6 @@ export class BinaryTree<
|
|
|
953
893
|
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
954
894
|
}
|
|
955
895
|
|
|
956
|
-
/**
|
|
957
|
-
* Time Complexity: O(n)
|
|
958
|
-
* Space Complexity: O(1)
|
|
959
|
-
*/
|
|
960
|
-
|
|
961
896
|
/**
|
|
962
897
|
* Time Complexity: O(n)
|
|
963
898
|
* Space Complexity: O(1)
|
|
@@ -1016,11 +951,6 @@ export class BinaryTree<
|
|
|
1016
951
|
}
|
|
1017
952
|
}
|
|
1018
953
|
|
|
1019
|
-
/**
|
|
1020
|
-
* Time Complexity: O(n)
|
|
1021
|
-
* Space Complexity: O(1)
|
|
1022
|
-
*/
|
|
1023
|
-
|
|
1024
954
|
/**
|
|
1025
955
|
* Time Complexity: O(n)
|
|
1026
956
|
* Space Complexity: O(1)
|
|
@@ -1052,11 +982,6 @@ export class BinaryTree<
|
|
|
1052
982
|
return depth;
|
|
1053
983
|
}
|
|
1054
984
|
|
|
1055
|
-
/**
|
|
1056
|
-
* Time Complexity: O(n)
|
|
1057
|
-
* Space Complexity: O(1)
|
|
1058
|
-
*/
|
|
1059
|
-
|
|
1060
985
|
/**
|
|
1061
986
|
* Time Complexity: O(n)
|
|
1062
987
|
* Space Complexity: O(1)
|
|
@@ -1103,11 +1028,6 @@ export class BinaryTree<
|
|
|
1103
1028
|
}
|
|
1104
1029
|
}
|
|
1105
1030
|
|
|
1106
|
-
/**
|
|
1107
|
-
* Time Complexity: O(n)
|
|
1108
|
-
* Space Complexity: O(log n)
|
|
1109
|
-
*/
|
|
1110
|
-
|
|
1111
1031
|
/**
|
|
1112
1032
|
* Time Complexity: O(n)
|
|
1113
1033
|
* Space Complexity: O(log n)
|
|
@@ -1170,11 +1090,6 @@ export class BinaryTree<
|
|
|
1170
1090
|
}
|
|
1171
1091
|
}
|
|
1172
1092
|
|
|
1173
|
-
/**
|
|
1174
|
-
* Time Complexity: O(log n)
|
|
1175
|
-
* Space Complexity: O(log n)
|
|
1176
|
-
*/
|
|
1177
|
-
|
|
1178
1093
|
/**
|
|
1179
1094
|
* Time Complexity: O(log n)
|
|
1180
1095
|
* Space Complexity: O(log n)
|
|
@@ -1203,32 +1118,36 @@ export class BinaryTree<
|
|
|
1203
1118
|
return isReverse ? result.reverse() : result;
|
|
1204
1119
|
}
|
|
1205
1120
|
|
|
1206
|
-
/**
|
|
1207
|
-
* Time Complexity: O(log n)
|
|
1208
|
-
* Space Complexity: O(1)
|
|
1209
|
-
*/
|
|
1210
|
-
|
|
1211
1121
|
/**
|
|
1212
1122
|
* Time Complexity: O(log n)
|
|
1213
1123
|
* Space Complexity: O(1)
|
|
1214
1124
|
*
|
|
1215
|
-
* The `getLeftMost`
|
|
1216
|
-
*
|
|
1217
|
-
* @param {
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1220
|
-
* @param {
|
|
1221
|
-
*
|
|
1222
|
-
*
|
|
1125
|
+
* The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
|
|
1126
|
+
* tail-recursive iteration.
|
|
1127
|
+
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1128
|
+
* node of a binary tree or null if the tree is empty. It has a default value of `_DEFAULT_CALLBACK`
|
|
1129
|
+
* if not provided explicitly.
|
|
1130
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
|
|
1131
|
+
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1132
|
+
* tree. It can be either a reference to the root node of the tree (`R`), or a key, node, or entry in
|
|
1133
|
+
* the binary tree structure (`
|
|
1134
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
|
|
1135
|
+
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
1136
|
+
* possible values:
|
|
1137
|
+
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
1138
|
+
* leftmost node in the binary tree starting from the `beginRoot` node. If the `beginRoot` is `NIL`,
|
|
1139
|
+
* it returns the result of the callback function applied to `undefined`. If the `beginRoot` is not a
|
|
1140
|
+
* real node, it returns the result of the callback function applied
|
|
1223
1141
|
*/
|
|
1224
|
-
getLeftMost(
|
|
1142
|
+
getLeftMost<C extends BTNCallback<OptBTNOrNull<NODE>>>(
|
|
1143
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1225
1144
|
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1226
1145
|
iterationType: IterationType = this.iterationType
|
|
1227
|
-
):
|
|
1228
|
-
if (this.isNIL(beginRoot)) return
|
|
1146
|
+
): ReturnType<C> {
|
|
1147
|
+
if (this.isNIL(beginRoot)) return callback(undefined);
|
|
1229
1148
|
beginRoot = this.ensureNode(beginRoot);
|
|
1230
1149
|
|
|
1231
|
-
if (!this.isRealNode(beginRoot)) return beginRoot;
|
|
1150
|
+
if (!this.isRealNode(beginRoot)) return callback(beginRoot);
|
|
1232
1151
|
|
|
1233
1152
|
if (iterationType === 'RECURSIVE') {
|
|
1234
1153
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1236,45 +1155,49 @@ export class BinaryTree<
|
|
|
1236
1155
|
return dfs(cur.left);
|
|
1237
1156
|
};
|
|
1238
1157
|
|
|
1239
|
-
return dfs(beginRoot);
|
|
1158
|
+
return callback(dfs(beginRoot));
|
|
1240
1159
|
} else {
|
|
1241
1160
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1242
|
-
const dfs = trampoline((cur: NODE) => {
|
|
1161
|
+
const dfs = trampoline((cur: NODE): NODE => {
|
|
1243
1162
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1244
1163
|
return dfs.cont(cur.left);
|
|
1245
1164
|
});
|
|
1246
1165
|
|
|
1247
|
-
return dfs(beginRoot);
|
|
1166
|
+
return callback(dfs(beginRoot));
|
|
1248
1167
|
}
|
|
1249
1168
|
}
|
|
1250
1169
|
|
|
1251
|
-
/**
|
|
1252
|
-
* Time Complexity: O(log n)
|
|
1253
|
-
* Space Complexity: O(1)
|
|
1254
|
-
*/
|
|
1255
|
-
|
|
1256
1170
|
/**
|
|
1257
1171
|
* Time Complexity: O(log n)
|
|
1258
1172
|
* Space Complexity: O(1)
|
|
1259
1173
|
*
|
|
1260
|
-
* The `getRightMost`
|
|
1261
|
-
*
|
|
1262
|
-
* @param {
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1265
|
-
* @param {
|
|
1266
|
-
*
|
|
1267
|
-
*
|
|
1268
|
-
*
|
|
1269
|
-
|
|
1270
|
-
|
|
1174
|
+
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
1175
|
+
* or iterative traversal methods.
|
|
1176
|
+
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
1177
|
+
* of the operation. It has a generic type `C` which extends `BTNCallback<OptBTNOrNull<NODE>>`. The
|
|
1178
|
+
* default value for `callback` is `this._DEFAULT_CALLBACK` if it is not provided.
|
|
1179
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
|
|
1180
|
+
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1181
|
+
* tree. It can be either a reference to the root node of the tree (`this.root`) or a specific key,
|
|
1182
|
+
* node, or entry in the tree. If
|
|
1183
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
|
|
1184
|
+
* function specifies the type of iteration to be used when finding the rightmost node in a binary
|
|
1185
|
+
* tree. It can have two possible values:
|
|
1186
|
+
* @returns The `getRightMost` function returns the result of the callback function `C` applied to
|
|
1187
|
+
* the rightmost node in the binary tree. The rightmost node is found either through a recursive
|
|
1188
|
+
* depth-first search (if `iterationType` is 'RECURSIVE') or through an indirect implementation of
|
|
1189
|
+
* iteration using tail recursion optimization. The result of the callback function applied to the
|
|
1190
|
+
* rightmost node is returned
|
|
1191
|
+
*/
|
|
1192
|
+
getRightMost<C extends BTNCallback<OptBTNOrNull<NODE>>>(
|
|
1193
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1271
1194
|
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1272
1195
|
iterationType: IterationType = this.iterationType
|
|
1273
|
-
):
|
|
1274
|
-
if (this.isNIL(beginRoot)) return
|
|
1196
|
+
): ReturnType<C> {
|
|
1197
|
+
if (this.isNIL(beginRoot)) return callback(undefined);
|
|
1275
1198
|
// TODO support get right most by passing key in
|
|
1276
1199
|
beginRoot = this.ensureNode(beginRoot);
|
|
1277
|
-
if (!beginRoot) return beginRoot;
|
|
1200
|
+
if (!beginRoot) return callback(beginRoot);
|
|
1278
1201
|
|
|
1279
1202
|
if (iterationType === 'RECURSIVE') {
|
|
1280
1203
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1282,7 +1205,7 @@ export class BinaryTree<
|
|
|
1282
1205
|
return dfs(cur.right);
|
|
1283
1206
|
};
|
|
1284
1207
|
|
|
1285
|
-
return dfs(beginRoot);
|
|
1208
|
+
return callback(dfs(beginRoot));
|
|
1286
1209
|
} else {
|
|
1287
1210
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1288
1211
|
const dfs = trampoline((cur: NODE) => {
|
|
@@ -1290,15 +1213,10 @@ export class BinaryTree<
|
|
|
1290
1213
|
return dfs.cont(cur.right);
|
|
1291
1214
|
});
|
|
1292
1215
|
|
|
1293
|
-
return dfs(beginRoot);
|
|
1216
|
+
return callback(dfs(beginRoot));
|
|
1294
1217
|
}
|
|
1295
1218
|
}
|
|
1296
1219
|
|
|
1297
|
-
/**
|
|
1298
|
-
* Time Complexity: O(log n)
|
|
1299
|
-
* Space Complexity: O(1)
|
|
1300
|
-
*/
|
|
1301
|
-
|
|
1302
1220
|
/**
|
|
1303
1221
|
* Time Complexity: O(log n)
|
|
1304
1222
|
* Space Complexity: O(1)
|
|
@@ -1322,11 +1240,6 @@ export class BinaryTree<
|
|
|
1322
1240
|
}
|
|
1323
1241
|
}
|
|
1324
1242
|
|
|
1325
|
-
/**
|
|
1326
|
-
* Time Complexity: O(log n)
|
|
1327
|
-
* Space Complexity: O(1)
|
|
1328
|
-
*/
|
|
1329
|
-
|
|
1330
1243
|
/**
|
|
1331
1244
|
* Time Complexity: O(log n)
|
|
1332
1245
|
* Space Complexity: O(1)
|
|
@@ -1341,7 +1254,7 @@ export class BinaryTree<
|
|
|
1341
1254
|
if (!this.isRealNode(x)) return undefined;
|
|
1342
1255
|
|
|
1343
1256
|
if (this.isRealNode(x.right)) {
|
|
1344
|
-
return this.getLeftMost(x.right);
|
|
1257
|
+
return this.getLeftMost(node => node, x.right);
|
|
1345
1258
|
}
|
|
1346
1259
|
|
|
1347
1260
|
let y: OptBTNOrNull<NODE> = x.parent;
|
|
@@ -1356,8 +1269,7 @@ export class BinaryTree<
|
|
|
1356
1269
|
callback?: C,
|
|
1357
1270
|
pattern?: DFSOrderPattern,
|
|
1358
1271
|
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
1359
|
-
iterationType?: IterationType
|
|
1360
|
-
includeNull?: false
|
|
1272
|
+
iterationType?: IterationType
|
|
1361
1273
|
): ReturnType<C>[];
|
|
1362
1274
|
|
|
1363
1275
|
dfs<C extends BTNCallback<NODE | null>>(
|
|
@@ -1365,14 +1277,9 @@ export class BinaryTree<
|
|
|
1365
1277
|
pattern?: DFSOrderPattern,
|
|
1366
1278
|
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
1367
1279
|
iterationType?: IterationType,
|
|
1368
|
-
includeNull?:
|
|
1280
|
+
includeNull?: boolean
|
|
1369
1281
|
): ReturnType<C>[];
|
|
1370
1282
|
|
|
1371
|
-
/**
|
|
1372
|
-
* Time complexity: O(n)
|
|
1373
|
-
* Space complexity: O(n)
|
|
1374
|
-
*/
|
|
1375
|
-
|
|
1376
1283
|
/**
|
|
1377
1284
|
* Time complexity: O(n)
|
|
1378
1285
|
* Space complexity: O(n)
|
|
@@ -1400,95 +1307,12 @@ export class BinaryTree<
|
|
|
1400
1307
|
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1401
1308
|
pattern: DFSOrderPattern = 'IN',
|
|
1402
1309
|
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1403
|
-
iterationType: IterationType =
|
|
1310
|
+
iterationType: IterationType = this.iterationType,
|
|
1404
1311
|
includeNull = false
|
|
1405
1312
|
): ReturnType<C>[] {
|
|
1406
1313
|
beginRoot = this.ensureNode(beginRoot);
|
|
1407
1314
|
if (!beginRoot) return [];
|
|
1408
|
-
|
|
1409
|
-
if (iterationType === 'RECURSIVE') {
|
|
1410
|
-
const dfs = (node: OptBTNOrNull<NODE>) => {
|
|
1411
|
-
switch (pattern) {
|
|
1412
|
-
case 'IN':
|
|
1413
|
-
if (includeNull) {
|
|
1414
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1415
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1416
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1417
|
-
} else {
|
|
1418
|
-
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1419
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1420
|
-
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1421
|
-
}
|
|
1422
|
-
break;
|
|
1423
|
-
case 'PRE':
|
|
1424
|
-
if (includeNull) {
|
|
1425
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1426
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1427
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1428
|
-
} else {
|
|
1429
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1430
|
-
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1431
|
-
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1432
|
-
}
|
|
1433
|
-
break;
|
|
1434
|
-
case 'POST':
|
|
1435
|
-
if (includeNull) {
|
|
1436
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1437
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1438
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1439
|
-
} else {
|
|
1440
|
-
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1441
|
-
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1442
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
break;
|
|
1446
|
-
}
|
|
1447
|
-
};
|
|
1448
|
-
|
|
1449
|
-
dfs(beginRoot);
|
|
1450
|
-
} else {
|
|
1451
|
-
// 0: visit, 1: print
|
|
1452
|
-
const stack: { opt: 0 | 1; node: OptBTNOrNull<NODE> }[] = [{ opt: 0, node: beginRoot }];
|
|
1453
|
-
|
|
1454
|
-
while (stack.length > 0) {
|
|
1455
|
-
const cur = stack.pop();
|
|
1456
|
-
if (cur === undefined || this.isNIL(cur.node)) continue;
|
|
1457
|
-
if (includeNull) {
|
|
1458
|
-
if (cur.node === undefined) continue;
|
|
1459
|
-
} else {
|
|
1460
|
-
if (cur.node === null || cur.node === undefined) continue;
|
|
1461
|
-
}
|
|
1462
|
-
if (cur.opt === 1) {
|
|
1463
|
-
ans.push(callback(cur.node));
|
|
1464
|
-
} else {
|
|
1465
|
-
switch (pattern) {
|
|
1466
|
-
case 'IN':
|
|
1467
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1468
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1469
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1470
|
-
break;
|
|
1471
|
-
case 'PRE':
|
|
1472
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1473
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1474
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1475
|
-
break;
|
|
1476
|
-
case 'POST':
|
|
1477
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1478
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1479
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1480
|
-
break;
|
|
1481
|
-
default:
|
|
1482
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1483
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1484
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1485
|
-
break;
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
return ans;
|
|
1315
|
+
return this._dfs(callback, pattern, beginRoot, iterationType, includeNull);
|
|
1492
1316
|
}
|
|
1493
1317
|
|
|
1494
1318
|
bfs<C extends BTNCallback<NODE>>(
|
|
@@ -1505,11 +1329,6 @@ export class BinaryTree<
|
|
|
1505
1329
|
includeNull?: true
|
|
1506
1330
|
): ReturnType<C>[];
|
|
1507
1331
|
|
|
1508
|
-
/**
|
|
1509
|
-
* Time complexity: O(n)
|
|
1510
|
-
* Space complexity: O(n)
|
|
1511
|
-
*/
|
|
1512
|
-
|
|
1513
1332
|
/**
|
|
1514
1333
|
* Time complexity: O(n)
|
|
1515
1334
|
* Space complexity: O(n)
|
|
@@ -1553,8 +1372,8 @@ export class BinaryTree<
|
|
|
1553
1372
|
ans.push(callback(current));
|
|
1554
1373
|
|
|
1555
1374
|
if (includeNull) {
|
|
1556
|
-
if (current && this.
|
|
1557
|
-
if (current && this.
|
|
1375
|
+
if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);
|
|
1376
|
+
if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);
|
|
1558
1377
|
} else {
|
|
1559
1378
|
if (this.isRealNode(current.left)) queue.push(current.left);
|
|
1560
1379
|
if (this.isRealNode(current.right)) queue.push(current.right);
|
|
@@ -1574,8 +1393,8 @@ export class BinaryTree<
|
|
|
1574
1393
|
ans.push(callback(current));
|
|
1575
1394
|
|
|
1576
1395
|
if (includeNull) {
|
|
1577
|
-
if (current && this.
|
|
1578
|
-
if (current && this.
|
|
1396
|
+
if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);
|
|
1397
|
+
if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);
|
|
1579
1398
|
} else {
|
|
1580
1399
|
if (this.isRealNode(current.left)) queue.push(current.left);
|
|
1581
1400
|
if (this.isRealNode(current.right)) queue.push(current.right);
|
|
@@ -1586,6 +1405,63 @@ export class BinaryTree<
|
|
|
1586
1405
|
return ans;
|
|
1587
1406
|
}
|
|
1588
1407
|
|
|
1408
|
+
/**
|
|
1409
|
+
* Time complexity: O(n)
|
|
1410
|
+
* Space complexity: O(n)
|
|
1411
|
+
*
|
|
1412
|
+
* The `leaves` function in TypeScript iterates through a binary tree to find and return the leaf
|
|
1413
|
+
* nodes based on a specified callback and iteration type.
|
|
1414
|
+
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1415
|
+
* in the binary tree. It is a generic type `C` that extends `BTNCallback<NODE | null>`, where `NODE`
|
|
1416
|
+
* represents a node in the binary tree. The default value for `callback` is
|
|
1417
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `leaves`
|
|
1418
|
+
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1419
|
+
* tree. It represents the root node of the binary tree or a specific key, node, or entry within the
|
|
1420
|
+
* tree from which the search for leaves should begin
|
|
1421
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
|
|
1422
|
+
* specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
|
|
1423
|
+
* can have two possible values:
|
|
1424
|
+
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1425
|
+
* provided callback function to the leaf nodes in the binary tree structure.
|
|
1426
|
+
*/
|
|
1427
|
+
leaves<C extends BTNCallback<NODE | null>>(
|
|
1428
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1429
|
+
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1430
|
+
iterationType: IterationType = this.iterationType
|
|
1431
|
+
): ReturnType<C>[] {
|
|
1432
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1433
|
+
const leaves: ReturnType<BTNCallback<NODE>>[] = [];
|
|
1434
|
+
if (!this.isRealNode(beginRoot)) {
|
|
1435
|
+
return [];
|
|
1436
|
+
}
|
|
1437
|
+
if (iterationType === 'RECURSIVE') {
|
|
1438
|
+
const dfs = (cur: NODE) => {
|
|
1439
|
+
if (this.isLeaf(cur)) {
|
|
1440
|
+
leaves.push(callback(cur));
|
|
1441
|
+
}
|
|
1442
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
1443
|
+
this.isRealNode(cur.left) && dfs(cur.left);
|
|
1444
|
+
this.isRealNode(cur.right) && dfs(cur.right);
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1447
|
+
dfs(beginRoot);
|
|
1448
|
+
} else {
|
|
1449
|
+
const queue = new Queue([beginRoot]);
|
|
1450
|
+
while (queue.size > 0) {
|
|
1451
|
+
const cur = queue.shift();
|
|
1452
|
+
if (this.isRealNode(cur)) {
|
|
1453
|
+
if (this.isLeaf(cur)) {
|
|
1454
|
+
leaves.push(callback(cur));
|
|
1455
|
+
}
|
|
1456
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
1457
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
return leaves;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1589
1465
|
listLevels<C extends BTNCallback<NODE>>(
|
|
1590
1466
|
callback?: C,
|
|
1591
1467
|
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
@@ -1600,11 +1476,6 @@ export class BinaryTree<
|
|
|
1600
1476
|
includeNull?: true
|
|
1601
1477
|
): ReturnType<C>[][];
|
|
1602
1478
|
|
|
1603
|
-
/**
|
|
1604
|
-
* Time complexity: O(n)
|
|
1605
|
-
* Space complexity: O(n)
|
|
1606
|
-
*/
|
|
1607
|
-
|
|
1608
1479
|
/**
|
|
1609
1480
|
* Time complexity: O(n)
|
|
1610
1481
|
* Space complexity: O(n)
|
|
@@ -1641,8 +1512,8 @@ export class BinaryTree<
|
|
|
1641
1512
|
if (!levelsNodes[level]) levelsNodes[level] = [];
|
|
1642
1513
|
levelsNodes[level].push(callback(node));
|
|
1643
1514
|
if (includeNull) {
|
|
1644
|
-
if (node && this.
|
|
1645
|
-
if (node && this.
|
|
1515
|
+
if (node && this.isRealNodeOrNull(node.left)) _recursive(node.left, level + 1);
|
|
1516
|
+
if (node && this.isRealNodeOrNull(node.right)) _recursive(node.right, level + 1);
|
|
1646
1517
|
} else {
|
|
1647
1518
|
if (node && node.left) _recursive(node.left, level + 1);
|
|
1648
1519
|
if (node && node.right) _recursive(node.right, level + 1);
|
|
@@ -1661,8 +1532,8 @@ export class BinaryTree<
|
|
|
1661
1532
|
levelsNodes[level].push(callback(node));
|
|
1662
1533
|
|
|
1663
1534
|
if (includeNull) {
|
|
1664
|
-
if (node && this.
|
|
1665
|
-
if (node && this.
|
|
1535
|
+
if (node && this.isRealNodeOrNull(node.right)) stack.push([node.right, level + 1]);
|
|
1536
|
+
if (node && this.isRealNodeOrNull(node.left)) stack.push([node.left, level + 1]);
|
|
1666
1537
|
} else {
|
|
1667
1538
|
if (node && node.right) stack.push([node.right, level + 1]);
|
|
1668
1539
|
if (node && node.left) stack.push([node.left, level + 1]);
|
|
@@ -1673,11 +1544,6 @@ export class BinaryTree<
|
|
|
1673
1544
|
return levelsNodes;
|
|
1674
1545
|
}
|
|
1675
1546
|
|
|
1676
|
-
/**
|
|
1677
|
-
* Time complexity: O(n)
|
|
1678
|
-
* Space complexity: O(n)
|
|
1679
|
-
*/
|
|
1680
|
-
|
|
1681
1547
|
/**
|
|
1682
1548
|
* Time complexity: O(n)
|
|
1683
1549
|
* Space complexity: O(n)
|
|
@@ -1783,11 +1649,6 @@ export class BinaryTree<
|
|
|
1783
1649
|
return ans;
|
|
1784
1650
|
}
|
|
1785
1651
|
|
|
1786
|
-
/**
|
|
1787
|
-
* Time complexity: O(n)
|
|
1788
|
-
* Space complexity: O(n)
|
|
1789
|
-
*/
|
|
1790
|
-
|
|
1791
1652
|
/**
|
|
1792
1653
|
* Time complexity: O(n)
|
|
1793
1654
|
* Space complexity: O(n)
|
|
@@ -1809,11 +1670,6 @@ export class BinaryTree<
|
|
|
1809
1670
|
return cloned;
|
|
1810
1671
|
}
|
|
1811
1672
|
|
|
1812
|
-
/**
|
|
1813
|
-
* Time Complexity: O(n)
|
|
1814
|
-
* Space Complexity: O(n)
|
|
1815
|
-
*/
|
|
1816
|
-
|
|
1817
1673
|
/**
|
|
1818
1674
|
* Time Complexity: O(n)
|
|
1819
1675
|
* Space Complexity: O(n)
|
|
@@ -1840,11 +1696,6 @@ export class BinaryTree<
|
|
|
1840
1696
|
return newTree;
|
|
1841
1697
|
}
|
|
1842
1698
|
|
|
1843
|
-
/**
|
|
1844
|
-
* Time Complexity: O(n)
|
|
1845
|
-
* Space Complexity: O(n)
|
|
1846
|
-
*/
|
|
1847
|
-
|
|
1848
1699
|
/**
|
|
1849
1700
|
* Time Complexity: O(n)
|
|
1850
1701
|
* Space Complexity: O(n)
|
|
@@ -1879,11 +1730,6 @@ export class BinaryTree<
|
|
|
1879
1730
|
// // }
|
|
1880
1731
|
//
|
|
1881
1732
|
|
|
1882
|
-
/**
|
|
1883
|
-
* Time Complexity: O(n)
|
|
1884
|
-
* Space Complexity: O(n)
|
|
1885
|
-
*/
|
|
1886
|
-
|
|
1887
1733
|
/**
|
|
1888
1734
|
* Time Complexity: O(n)
|
|
1889
1735
|
* Space Complexity: O(n)
|
|
@@ -1898,35 +1744,185 @@ export class BinaryTree<
|
|
|
1898
1744
|
* @returns Nothing is being returned. The function has a return type of `void`, which means it does
|
|
1899
1745
|
* not return any value.
|
|
1900
1746
|
*/
|
|
1901
|
-
override print(beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions):
|
|
1747
|
+
override print(beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions): string {
|
|
1902
1748
|
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1903
1749
|
beginRoot = this.ensureNode(beginRoot);
|
|
1904
|
-
|
|
1750
|
+
let output = '';
|
|
1751
|
+
if (!beginRoot) return output;
|
|
1905
1752
|
|
|
1906
1753
|
if (opts.isShowUndefined)
|
|
1907
|
-
|
|
1908
|
-
|
|
1754
|
+
output += `U for undefined
|
|
1755
|
+
`;
|
|
1909
1756
|
if (opts.isShowNull)
|
|
1910
|
-
|
|
1911
|
-
|
|
1757
|
+
output += `N for null
|
|
1758
|
+
`;
|
|
1912
1759
|
if (opts.isShowRedBlackNIL)
|
|
1913
|
-
|
|
1914
|
-
|
|
1760
|
+
output += `S for Sentinel Node(NIL)
|
|
1761
|
+
`;
|
|
1915
1762
|
|
|
1916
1763
|
const display = (root: OptBTNOrNull<NODE>): void => {
|
|
1917
1764
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1765
|
+
let paragraph = '';
|
|
1918
1766
|
for (const line of lines) {
|
|
1919
|
-
|
|
1767
|
+
paragraph += line + '\n';
|
|
1920
1768
|
}
|
|
1769
|
+
output += paragraph;
|
|
1921
1770
|
};
|
|
1922
1771
|
|
|
1923
1772
|
display(beginRoot);
|
|
1773
|
+
return output;
|
|
1924
1774
|
}
|
|
1925
1775
|
|
|
1776
|
+
protected _dfs<C extends BTNCallback<NODE>>(
|
|
1777
|
+
callback?: C,
|
|
1778
|
+
pattern?: DFSOrderPattern,
|
|
1779
|
+
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
1780
|
+
iterationType?: IterationType
|
|
1781
|
+
): ReturnType<C>[];
|
|
1782
|
+
|
|
1783
|
+
protected _dfs<C extends BTNCallback<NODE | null>>(
|
|
1784
|
+
callback?: C,
|
|
1785
|
+
pattern?: DFSOrderPattern,
|
|
1786
|
+
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
|
1787
|
+
iterationType?: IterationType,
|
|
1788
|
+
includeNull?: boolean
|
|
1789
|
+
): ReturnType<C>[];
|
|
1790
|
+
|
|
1926
1791
|
/**
|
|
1927
|
-
* Time
|
|
1928
|
-
* Space
|
|
1929
|
-
|
|
1792
|
+
* Time complexity: O(n)
|
|
1793
|
+
* Space complexity: O(n)
|
|
1794
|
+
*
|
|
1795
|
+
* The function `_dfs` performs a depth-first search traversal on a binary tree structure based on
|
|
1796
|
+
* the specified order pattern and callback function.
|
|
1797
|
+
* @param {C} callback - The `callback` parameter is a function that will be called on each node
|
|
1798
|
+
* visited during the depth-first search. It is of type `C`, which extends
|
|
1799
|
+
* `BTNCallback<OptBTNOrNull<NODE>>`. The default value is set to `this._DEFAULT_CALLBACK` if not
|
|
1800
|
+
* provided.
|
|
1801
|
+
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1802
|
+
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in a binary tree.
|
|
1803
|
+
* It can have one of the following values:
|
|
1804
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `_dfs`
|
|
1805
|
+
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1806
|
+
* tree. It can be provided as either the root node of the tree or a key, node, or entry that exists
|
|
1807
|
+
* in the tree. If no specific `
|
|
1808
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1809
|
+
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal. It
|
|
1810
|
+
* can have two possible values:
|
|
1811
|
+
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method is a boolean flag
|
|
1812
|
+
* that determines whether null nodes should be included in the depth-first search traversal. If
|
|
1813
|
+
* `includeNull` is set to `true`, the traversal will consider null nodes as valid nodes to visit and
|
|
1814
|
+
* process. If set to `
|
|
1815
|
+
* @param shouldVisitLeft - The `shouldVisitLeft` parameter is a function that takes a node as input
|
|
1816
|
+
* and returns a boolean value. It is used to determine whether the left child of a node should be
|
|
1817
|
+
* visited during the depth-first search traversal. By default, it checks if the node is truthy (not
|
|
1818
|
+
* null or undefined
|
|
1819
|
+
* @param shouldVisitRight - The `shouldVisitRight` parameter is a function that takes a node as
|
|
1820
|
+
* input and returns a boolean value. It is used to determine whether the right child of a node
|
|
1821
|
+
* should be visited during the depth-first search traversal. The default implementation checks if
|
|
1822
|
+
* the node is truthy before visiting the right child.
|
|
1823
|
+
* @param shouldVisitRoot - The `shouldVisitRoot` parameter is a function that takes a node as an
|
|
1824
|
+
* argument and returns a boolean value. It is used to determine whether a given node should be
|
|
1825
|
+
* visited during the depth-first search traversal based on certain conditions. The default
|
|
1826
|
+
* implementation checks if the node is a real node or null based
|
|
1827
|
+
* @param shouldProcessRoot - The `shouldProcessRoot` parameter is a function that takes a node as
|
|
1828
|
+
* input and returns a boolean value indicating whether the node should be processed during the
|
|
1829
|
+
* depth-first search traversal. The default implementation of this function simply returns `true`,
|
|
1830
|
+
* meaning that by default all nodes will be processed. However, you can
|
|
1831
|
+
* @returns The `_dfs` method returns an array of the return type of the callback function provided
|
|
1832
|
+
* as input.
|
|
1833
|
+
*/
|
|
1834
|
+
protected _dfs<C extends BTNCallback<OptBTNOrNull<NODE>>>(
|
|
1835
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1836
|
+
pattern: DFSOrderPattern = 'IN',
|
|
1837
|
+
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1838
|
+
iterationType: IterationType = this.iterationType,
|
|
1839
|
+
includeNull = false,
|
|
1840
|
+
shouldVisitLeft: (node: OptBTNOrNull<NODE>) => boolean = node => !!node,
|
|
1841
|
+
shouldVisitRight: (node: OptBTNOrNull<NODE>) => boolean = node => !!node,
|
|
1842
|
+
shouldVisitRoot: (node: OptBTNOrNull<NODE>) => boolean = node => {
|
|
1843
|
+
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1844
|
+
return this.isRealNode(node);
|
|
1845
|
+
},
|
|
1846
|
+
shouldProcessRoot: (node: OptBTNOrNull<NODE>) => boolean = node => true
|
|
1847
|
+
): ReturnType<C>[] {
|
|
1848
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1849
|
+
if (!beginRoot) return [];
|
|
1850
|
+
const ans: ReturnType<C>[] = [];
|
|
1851
|
+
|
|
1852
|
+
if (iterationType === 'RECURSIVE') {
|
|
1853
|
+
const dfs = (node: OptBTNOrNull<NODE>) => {
|
|
1854
|
+
if (!shouldVisitRoot(node)) return;
|
|
1855
|
+
|
|
1856
|
+
const visitLeft = () => {
|
|
1857
|
+
if (shouldVisitLeft(node)) dfs(node?.left);
|
|
1858
|
+
};
|
|
1859
|
+
const visitRight = () => {
|
|
1860
|
+
if (shouldVisitRight(node)) dfs(node?.right);
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
switch (pattern) {
|
|
1864
|
+
case 'IN':
|
|
1865
|
+
visitLeft();
|
|
1866
|
+
if (shouldProcessRoot(node)) ans.push(callback(node));
|
|
1867
|
+
visitRight();
|
|
1868
|
+
break;
|
|
1869
|
+
case 'PRE':
|
|
1870
|
+
if (shouldProcessRoot(node)) ans.push(callback(node));
|
|
1871
|
+
visitLeft();
|
|
1872
|
+
visitRight();
|
|
1873
|
+
break;
|
|
1874
|
+
case 'POST':
|
|
1875
|
+
visitLeft();
|
|
1876
|
+
visitRight();
|
|
1877
|
+
if (shouldProcessRoot(node)) ans.push(callback(node));
|
|
1878
|
+
break;
|
|
1879
|
+
}
|
|
1880
|
+
};
|
|
1881
|
+
|
|
1882
|
+
dfs(beginRoot);
|
|
1883
|
+
} else {
|
|
1884
|
+
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node: beginRoot }];
|
|
1885
|
+
|
|
1886
|
+
const pushLeft = (cur: DFSStackItem<NODE>) => {
|
|
1887
|
+
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
1888
|
+
};
|
|
1889
|
+
const pushRight = (cur: DFSStackItem<NODE>) => {
|
|
1890
|
+
if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
|
|
1891
|
+
};
|
|
1892
|
+
const pushRoot = (cur: DFSStackItem<NODE>) => {
|
|
1893
|
+
if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
while (stack.length > 0) {
|
|
1897
|
+
const cur = stack.pop();
|
|
1898
|
+
if (cur === undefined) continue;
|
|
1899
|
+
if (!shouldVisitRoot(cur.node)) continue;
|
|
1900
|
+
if (cur.opt === DFSOperation.PROCESS) {
|
|
1901
|
+
if (shouldProcessRoot(cur.node)) ans.push(callback(cur.node));
|
|
1902
|
+
} else {
|
|
1903
|
+
switch (pattern) {
|
|
1904
|
+
case 'IN':
|
|
1905
|
+
pushRight(cur);
|
|
1906
|
+
pushRoot(cur);
|
|
1907
|
+
pushLeft(cur);
|
|
1908
|
+
break;
|
|
1909
|
+
case 'PRE':
|
|
1910
|
+
pushRight(cur);
|
|
1911
|
+
pushLeft(cur);
|
|
1912
|
+
pushRoot(cur);
|
|
1913
|
+
break;
|
|
1914
|
+
case 'POST':
|
|
1915
|
+
pushRoot(cur);
|
|
1916
|
+
pushRight(cur);
|
|
1917
|
+
pushLeft(cur);
|
|
1918
|
+
break;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
return ans;
|
|
1925
|
+
}
|
|
1930
1926
|
|
|
1931
1927
|
/**
|
|
1932
1928
|
* Time Complexity: O(1)
|
|
@@ -1969,11 +1965,6 @@ export class BinaryTree<
|
|
|
1969
1965
|
}
|
|
1970
1966
|
}
|
|
1971
1967
|
|
|
1972
|
-
/**
|
|
1973
|
-
* Time Complexity: O(n)
|
|
1974
|
-
* Space Complexity: O(n)
|
|
1975
|
-
*/
|
|
1976
|
-
|
|
1977
1968
|
/**
|
|
1978
1969
|
* Time Complexity: O(n)
|
|
1979
1970
|
* Space Complexity: O(n)
|
|
@@ -2061,11 +2052,6 @@ export class BinaryTree<
|
|
|
2061
2052
|
|
|
2062
2053
|
protected _DEFAULT_CALLBACK = (node: OptBTNOrNull<NODE>) => (node ? node.key : undefined);
|
|
2063
2054
|
|
|
2064
|
-
/**
|
|
2065
|
-
* Time Complexity: O(1)
|
|
2066
|
-
* Space Complexity: O(1)
|
|
2067
|
-
*/
|
|
2068
|
-
|
|
2069
2055
|
/**
|
|
2070
2056
|
* Time Complexity: O(1)
|
|
2071
2057
|
* Space Complexity: O(1)
|
|
@@ -2103,11 +2089,6 @@ export class BinaryTree<
|
|
|
2103
2089
|
return undefined;
|
|
2104
2090
|
}
|
|
2105
2091
|
|
|
2106
|
-
/**
|
|
2107
|
-
* Time Complexity: O(1)
|
|
2108
|
-
* Space Complexity: O(1)
|
|
2109
|
-
*/
|
|
2110
|
-
|
|
2111
2092
|
/**
|
|
2112
2093
|
* Time Complexity: O(1)
|
|
2113
2094
|
* Space Complexity: O(1)
|
|
@@ -2138,11 +2119,6 @@ export class BinaryTree<
|
|
|
2138
2119
|
return newNode;
|
|
2139
2120
|
}
|
|
2140
2121
|
|
|
2141
|
-
/**
|
|
2142
|
-
* Time Complexity: O(1)
|
|
2143
|
-
* Space Complexity: O(1)
|
|
2144
|
-
*/
|
|
2145
|
-
|
|
2146
2122
|
/**
|
|
2147
2123
|
* Time Complexity: O(1)
|
|
2148
2124
|
* Space Complexity: O(1)
|
|
@@ -2159,11 +2135,6 @@ export class BinaryTree<
|
|
|
2159
2135
|
this._root = v;
|
|
2160
2136
|
}
|
|
2161
2137
|
|
|
2162
|
-
/**
|
|
2163
|
-
* Time Complexity: O(1)
|
|
2164
|
-
* Space Complexity: O(1)
|
|
2165
|
-
*/
|
|
2166
|
-
|
|
2167
2138
|
/**
|
|
2168
2139
|
* Time Complexity: O(1)
|
|
2169
2140
|
* Space Complexity: O(1)
|