data-structure-typed 1.41.0 → 1.41.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/CHANGELOG.md +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-indexed-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +6 -3
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +30 -8
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.js +2 -2
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +5 -4
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +42 -44
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/cjs/data-structures/binary-tree/tree-multiset.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/tree-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/tree-set.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/matrix/matrix.js.map +1 -1
- package/dist/cjs/data-structures/matrix/vector2d.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +6 -3
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +29 -8
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/bst.js +2 -2
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +5 -4
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +43 -45
- package/dist/mjs/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +9 -9
- package/src/data-structures/binary-tree/avl-tree.ts +3 -2
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +1 -1
- package/src/data-structures/binary-tree/binary-tree.ts +65 -17
- package/src/data-structures/binary-tree/bst.ts +7 -4
- package/src/data-structures/binary-tree/rb-tree.ts +47 -68
- package/src/data-structures/binary-tree/tree-multiset.ts +4 -3
- package/src/data-structures/graph/abstract-graph.ts +11 -12
- package/src/data-structures/graph/directed-graph.ts +7 -6
- package/src/data-structures/graph/undirected-graph.ts +7 -6
- package/src/data-structures/hash/hash-map.ts +1 -1
- package/src/data-structures/hash/tree-map.ts +1 -2
- package/src/data-structures/hash/tree-set.ts +1 -2
- package/src/data-structures/heap/heap.ts +2 -2
- package/src/data-structures/heap/max-heap.ts +1 -1
- package/src/data-structures/heap/min-heap.ts +1 -1
- package/src/data-structures/linked-list/doubly-linked-list.ts +1 -1
- package/src/data-structures/linked-list/singly-linked-list.ts +1 -1
- package/src/data-structures/matrix/matrix.ts +1 -1
- package/src/data-structures/matrix/vector2d.ts +1 -2
- package/src/data-structures/priority-queue/max-priority-queue.ts +1 -1
- package/src/data-structures/priority-queue/min-priority-queue.ts +1 -1
- package/src/data-structures/priority-queue/priority-queue.ts +1 -1
- package/src/data-structures/queue/deque.ts +3 -4
- package/src/data-structures/queue/queue.ts +1 -1
- package/src/types/data-structures/matrix/navigator.ts +1 -1
- package/src/types/utils/utils.ts +1 -1
- package/src/types/utils/validate-type.ts +2 -2
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +6 -6
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +11 -11
- package/test/unit/data-structures/binary-tree/bst.test.ts +22 -20
- package/test/unit/data-structures/binary-tree/overall.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +53 -17
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +8 -8
- package/test/utils/big-o.js +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.1",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/mjs/index.js",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"format:src": "prettier --write 'src/**/*.{js,ts}'",
|
|
27
27
|
"format:test": "prettier --write 'test/**/*.{js,ts}'",
|
|
28
28
|
"format": "npm run format:src && npm run format:test",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
29
|
+
"reformat:src": "npm run lint:src && npm run format:src",
|
|
30
|
+
"reformat:test": "npm run lint:test && npm run format:test",
|
|
31
|
+
"reformat": "npm run reformat:src && npm run reformat:test",
|
|
32
32
|
"update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed --save-dev",
|
|
33
33
|
"install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multiset-typed trie-typed undirected-graph-typed queue-typed --save-dev",
|
|
34
34
|
"test": "jest",
|
|
35
35
|
"check:deps": "dependency-cruiser src",
|
|
36
36
|
"changelog": "auto-changelog",
|
|
37
37
|
"coverage:badge": "istanbul-badges-readme",
|
|
38
|
-
"ci": "env && git fetch --tags && npm run lint && npm run build && npm run update:subs && npm run test && npm run changelog",
|
|
38
|
+
"ci": "env && git fetch --tags && npm run check && npm run lint && npm run build && npm run update:subs && npm run test && npm run changelog",
|
|
39
39
|
"copy:to-subs": "sh scripts/copy_to_all_subs.sh",
|
|
40
40
|
"publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh",
|
|
41
41
|
"publish:docs": "sh scripts/publish_docs.sh",
|
|
@@ -61,17 +61,17 @@
|
|
|
61
61
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
62
62
|
"@typescript-eslint/parser": "^6.7.4",
|
|
63
63
|
"auto-changelog": "^2.4.0",
|
|
64
|
-
"avl-tree-typed": "^1.
|
|
64
|
+
"avl-tree-typed": "^1.41.0",
|
|
65
65
|
"benchmark": "^2.1.4",
|
|
66
|
-
"binary-tree-typed": "^1.
|
|
67
|
-
"bst-typed": "^1.
|
|
66
|
+
"binary-tree-typed": "^1.41.0",
|
|
67
|
+
"bst-typed": "^1.41.0",
|
|
68
68
|
"dependency-cruiser": "^14.1.0",
|
|
69
69
|
"eslint": "^8.50.0",
|
|
70
70
|
"eslint-config-prettier": "^9.0.0",
|
|
71
71
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
72
72
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
73
73
|
"eslint-plugin-import": "^2.28.1",
|
|
74
|
-
"heap-typed": "^1.
|
|
74
|
+
"heap-typed": "^1.41.0",
|
|
75
75
|
"istanbul-badges-readme": "^1.8.5",
|
|
76
76
|
"jest": "^29.7.0",
|
|
77
77
|
"prettier": "^3.0.3",
|
|
@@ -21,7 +21,8 @@ export class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNeste
|
|
|
21
21
|
|
|
22
22
|
export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>>
|
|
23
23
|
extends BST<V, N>
|
|
24
|
-
implements IBinaryTree<V, N>
|
|
24
|
+
implements IBinaryTree<V, N>
|
|
25
|
+
{
|
|
25
26
|
/**
|
|
26
27
|
* This is a constructor function for an AVL tree data structure in TypeScript.
|
|
27
28
|
* @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the
|
|
@@ -160,7 +161,7 @@ export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTr
|
|
|
160
161
|
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
|
|
161
162
|
switch (
|
|
162
163
|
this._balanceFactor(A) // second O(1)
|
|
163
|
-
|
|
164
|
+
) {
|
|
164
165
|
case -2:
|
|
165
166
|
if (A && A.left) {
|
|
166
167
|
if (this._balanceFactor(A.left) <= 0) {
|
|
@@ -17,7 +17,7 @@ export class BinaryIndexedTree {
|
|
|
17
17
|
* @param - - `frequency`: The default frequency value. It is optional and has a default
|
|
18
18
|
* value of 0.
|
|
19
19
|
*/
|
|
20
|
-
constructor({frequency = 0, max}: {
|
|
20
|
+
constructor({frequency = 0, max}: {frequency?: number; max: number}) {
|
|
21
21
|
this._freq = frequency;
|
|
22
22
|
this._max = max;
|
|
23
23
|
this._freqMap = {0: 0};
|
|
@@ -108,7 +108,8 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
108
108
|
* @template N - The type of the binary tree's nodes.
|
|
109
109
|
*/
|
|
110
110
|
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
|
|
111
|
-
implements IBinaryTree<V, N>
|
|
111
|
+
implements IBinaryTree<V, N>
|
|
112
|
+
{
|
|
112
113
|
iterationType: IterationType = IterationType.ITERATIVE;
|
|
113
114
|
|
|
114
115
|
/**
|
|
@@ -201,7 +202,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
|
|
204
|
-
const existNode = key !== undefined ? this.
|
|
205
|
+
const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
|
|
205
206
|
|
|
206
207
|
if (this.root) {
|
|
207
208
|
if (existNode) {
|
|
@@ -290,7 +291,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
290
291
|
if (!this.root) return bstDeletedResult;
|
|
291
292
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
292
293
|
|
|
293
|
-
const curr = this.
|
|
294
|
+
const curr = this.getNode(identifier, callback);
|
|
294
295
|
if (!curr) return bstDeletedResult;
|
|
295
296
|
|
|
296
297
|
const parent: N | null = curr?.parent ? curr.parent : null;
|
|
@@ -342,8 +343,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
342
343
|
* @returns the depth of the `distNode` relative to the `beginRoot`.
|
|
343
344
|
*/
|
|
344
345
|
getDepth(distNode: BTNKey | N | null, beginRoot: BTNKey | N | null = this.root): number {
|
|
345
|
-
if (typeof distNode === 'number') distNode = this.
|
|
346
|
-
if (typeof beginRoot === 'number') beginRoot = this.
|
|
346
|
+
if (typeof distNode === 'number') distNode = this.getNode(distNode);
|
|
347
|
+
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
347
348
|
let depth = 0;
|
|
348
349
|
while (distNode?.parent) {
|
|
349
350
|
if (distNode === beginRoot) {
|
|
@@ -368,7 +369,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
368
369
|
* @returns the height of the binary tree.
|
|
369
370
|
*/
|
|
370
371
|
getHeight(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): number {
|
|
371
|
-
if (typeof beginRoot === 'number') beginRoot = this.
|
|
372
|
+
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
372
373
|
if (!beginRoot) return -1;
|
|
373
374
|
|
|
374
375
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -385,7 +386,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
385
386
|
return -1;
|
|
386
387
|
}
|
|
387
388
|
|
|
388
|
-
const stack: {
|
|
389
|
+
const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];
|
|
389
390
|
let maxHeight = 0;
|
|
390
391
|
|
|
391
392
|
while (stack.length > 0) {
|
|
@@ -604,21 +605,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
604
605
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
605
606
|
}
|
|
606
607
|
|
|
607
|
-
|
|
608
|
+
getNode<C extends BTNCallback<N, BTNKey>>(
|
|
608
609
|
identifier: BTNKey,
|
|
609
610
|
callback?: C,
|
|
610
611
|
beginRoot?: N,
|
|
611
612
|
iterationType?: IterationType
|
|
612
613
|
): N | null;
|
|
613
614
|
|
|
614
|
-
|
|
615
|
+
getNode<C extends BTNCallback<N, N>>(
|
|
615
616
|
identifier: N | null,
|
|
616
617
|
callback?: C,
|
|
617
618
|
beginRoot?: N,
|
|
618
619
|
iterationType?: IterationType
|
|
619
620
|
): N | null;
|
|
620
621
|
|
|
621
|
-
|
|
622
|
+
getNode<C extends BTNCallback<N>>(
|
|
622
623
|
identifier: ReturnType<C>,
|
|
623
624
|
callback: C,
|
|
624
625
|
beginRoot?: N,
|
|
@@ -640,7 +641,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
640
641
|
* performed when searching for a node in the binary tree. It can have one of the following values:
|
|
641
642
|
* @returns either the found node (of type N) or null if no node is found.
|
|
642
643
|
*/
|
|
643
|
-
|
|
644
|
+
getNode<C extends BTNCallback<N>>(
|
|
644
645
|
identifier: ReturnType<C> | null,
|
|
645
646
|
callback: C = ((node: N) => node.key) as C,
|
|
646
647
|
beginRoot = this.root,
|
|
@@ -651,6 +652,53 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
651
652
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
652
653
|
}
|
|
653
654
|
|
|
655
|
+
get<C extends BTNCallback<N, BTNKey>>(
|
|
656
|
+
identifier: BTNKey,
|
|
657
|
+
callback?: C,
|
|
658
|
+
beginRoot?: N,
|
|
659
|
+
iterationType?: IterationType
|
|
660
|
+
): V | undefined;
|
|
661
|
+
|
|
662
|
+
get<C extends BTNCallback<N, N>>(
|
|
663
|
+
identifier: N | null,
|
|
664
|
+
callback?: C,
|
|
665
|
+
beginRoot?: N,
|
|
666
|
+
iterationType?: IterationType
|
|
667
|
+
): V | undefined;
|
|
668
|
+
|
|
669
|
+
get<C extends BTNCallback<N>>(
|
|
670
|
+
identifier: ReturnType<C>,
|
|
671
|
+
callback: C,
|
|
672
|
+
beginRoot?: N,
|
|
673
|
+
iterationType?: IterationType
|
|
674
|
+
): V | undefined;
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* The function `get` returns the first node value in a binary tree that matches the given property or key.
|
|
678
|
+
* @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
|
|
679
|
+
* the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`
|
|
680
|
+
* type.
|
|
681
|
+
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
682
|
+
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
683
|
+
* whether the node matches the criteria or not. The default callback function
|
|
684
|
+
* (`((node: N) => node.key)`) is used if no callback function is
|
|
685
|
+
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
686
|
+
* the root node from which the search should begin.
|
|
687
|
+
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
688
|
+
* performed when searching for a node in the binary tree. It can have one of the following values:
|
|
689
|
+
* @returns either the found value (of type V) or undefined if no node value is found.
|
|
690
|
+
*/
|
|
691
|
+
get<C extends BTNCallback<N>>(
|
|
692
|
+
identifier: ReturnType<C> | null,
|
|
693
|
+
callback: C = ((node: N) => node.key) as C,
|
|
694
|
+
beginRoot = this.root,
|
|
695
|
+
iterationType = this.iterationType
|
|
696
|
+
): V | undefined {
|
|
697
|
+
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
698
|
+
// TODO may support finding node by value equal
|
|
699
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0].value ?? undefined;
|
|
700
|
+
}
|
|
701
|
+
|
|
654
702
|
/**
|
|
655
703
|
* The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
|
|
656
704
|
* up to the root node, with the option to reverse the order of the nodes.
|
|
@@ -686,7 +734,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
686
734
|
* no leftmost node, it returns `null`.
|
|
687
735
|
*/
|
|
688
736
|
getLeftMost(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): N | null {
|
|
689
|
-
if (typeof beginRoot === 'number') beginRoot = this.
|
|
737
|
+
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
690
738
|
|
|
691
739
|
if (!beginRoot) return beginRoot;
|
|
692
740
|
|
|
@@ -812,7 +860,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
812
860
|
beginRoot: BTNKey | N | null = this.root,
|
|
813
861
|
iterationType = this.iterationType
|
|
814
862
|
): ReturnType<C>[] {
|
|
815
|
-
if (typeof beginRoot === 'number') beginRoot = this.
|
|
863
|
+
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
816
864
|
|
|
817
865
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
818
866
|
if (!beginRoot) return ans;
|
|
@@ -888,7 +936,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
888
936
|
_traverse(beginRoot);
|
|
889
937
|
} else {
|
|
890
938
|
// 0: visit, 1: print
|
|
891
|
-
const stack: {
|
|
939
|
+
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];
|
|
892
940
|
|
|
893
941
|
while (stack.length > 0) {
|
|
894
942
|
const cur = stack.pop();
|
|
@@ -960,7 +1008,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
960
1008
|
if (current.right) queue.push(current.right);
|
|
961
1009
|
|
|
962
1010
|
traverse(level + 1);
|
|
963
|
-
}
|
|
1011
|
+
};
|
|
964
1012
|
|
|
965
1013
|
traverse(0);
|
|
966
1014
|
} else {
|
|
@@ -1055,7 +1103,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1055
1103
|
* @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null`
|
|
1056
1104
|
* if there is no successor, or `undefined` if the input `x` is `undefined`.
|
|
1057
1105
|
*/
|
|
1058
|
-
getSuccessor(x: N): N | null | undefined{
|
|
1106
|
+
getSuccessor(x: N): N | null | undefined {
|
|
1059
1107
|
if (x.right) {
|
|
1060
1108
|
return this.getLeftMost(x.right);
|
|
1061
1109
|
}
|
|
@@ -1178,7 +1226,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1178
1226
|
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
|
1179
1227
|
* binary tree nodes in a specific order.
|
|
1180
1228
|
*/
|
|
1181
|
-
*
|
|
1229
|
+
*[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
|
|
1182
1230
|
if (!node) {
|
|
1183
1231
|
return;
|
|
1184
1232
|
}
|
|
@@ -19,7 +19,8 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
19
19
|
|
|
20
20
|
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>
|
|
21
21
|
extends BinaryTree<V, N>
|
|
22
|
-
implements IBinaryTree<V, N>
|
|
22
|
+
implements IBinaryTree<V, N>
|
|
23
|
+
{
|
|
23
24
|
/**
|
|
24
25
|
* The constructor function initializes a binary search tree object with an optional comparator
|
|
25
26
|
* function.
|
|
@@ -153,7 +154,9 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
153
154
|
return super.addMany(keysOrNodes, data);
|
|
154
155
|
}
|
|
155
156
|
const inserted: (N | null | undefined)[] = [];
|
|
156
|
-
const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(
|
|
157
|
+
const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(
|
|
158
|
+
(value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]
|
|
159
|
+
);
|
|
157
160
|
let sorted = [];
|
|
158
161
|
|
|
159
162
|
function isNodeOrNullTuple(arr: [BTNKey | N, V][]): arr is [N, V][] {
|
|
@@ -231,7 +234,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
231
234
|
* @returns either the first node that matches the given nodeProperty and callback, or null if no
|
|
232
235
|
* matching node is found.
|
|
233
236
|
*/
|
|
234
|
-
override
|
|
237
|
+
override getNode<C extends BTNCallback<N>>(
|
|
235
238
|
identifier: ReturnType<C> | null,
|
|
236
239
|
callback: C = ((node: N) => node.key) as C,
|
|
237
240
|
beginRoot = this.root,
|
|
@@ -362,7 +365,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
362
365
|
targetNode: BTNKey | N | null = this.root,
|
|
363
366
|
iterationType = this.iterationType
|
|
364
367
|
): ReturnType<C>[] {
|
|
365
|
-
if (typeof targetNode === 'number') targetNode = this.
|
|
368
|
+
if (typeof targetNode === 'number') targetNode = this.getNode(targetNode);
|
|
366
369
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
367
370
|
if (!targetNode) return ans;
|
|
368
371
|
const targetKey = targetNode.key;
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
import {RBTNColor} from
|
|
1
|
+
import {RBTNColor} from '../../types';
|
|
2
2
|
|
|
3
3
|
export class RBTreeNode {
|
|
4
|
-
key: number
|
|
4
|
+
key: number;
|
|
5
5
|
parent: RBTreeNode;
|
|
6
6
|
left: RBTreeNode;
|
|
7
7
|
right: RBTreeNode;
|
|
8
8
|
color: number = RBTNColor.BLACK;
|
|
9
9
|
|
|
10
|
-
constructor() {
|
|
10
|
+
constructor(key: number, color: RBTNColor = RBTNColor.BLACK) {
|
|
11
|
+
this.key = key;
|
|
12
|
+
this.color = color;
|
|
11
13
|
this.parent = null as unknown as RBTreeNode;
|
|
12
14
|
this.left = null as unknown as RBTreeNode;
|
|
13
15
|
this.right = null as unknown as RBTreeNode;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
|
|
19
|
+
export const SN = new RBTreeNode(0);
|
|
20
|
+
|
|
17
21
|
export class RedBlackTree {
|
|
18
|
-
|
|
19
22
|
constructor() {
|
|
20
|
-
this.
|
|
21
|
-
this.NIL.color = RBTNColor.BLACK;
|
|
22
|
-
this.NIL.left = null as unknown as RBTreeNode;
|
|
23
|
-
this.NIL.right = null as unknown as RBTreeNode;
|
|
24
|
-
this._root = this.NIL;
|
|
23
|
+
this._root = SN;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
protected _root: RBTreeNode;
|
|
@@ -30,12 +29,6 @@ export class RedBlackTree {
|
|
|
30
29
|
return this._root;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
protected _NIL: RBTreeNode;
|
|
34
|
-
|
|
35
|
-
get NIL(): RBTreeNode {
|
|
36
|
-
return this._NIL;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
32
|
/**
|
|
40
33
|
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
41
34
|
* violations of the red-black tree properties.
|
|
@@ -44,18 +37,14 @@ export class RedBlackTree {
|
|
|
44
37
|
* @returns The function does not explicitly return anything.
|
|
45
38
|
*/
|
|
46
39
|
insert(key: number): void {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
node.
|
|
50
|
-
node.key = key;
|
|
51
|
-
node.left = this.NIL;
|
|
52
|
-
node.right = this.NIL;
|
|
53
|
-
node.color = RBTNColor.RED;
|
|
40
|
+
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
41
|
+
node.left = SN;
|
|
42
|
+
node.right = SN;
|
|
54
43
|
|
|
55
44
|
let y: RBTreeNode = null as unknown as RBTreeNode;
|
|
56
45
|
let x: RBTreeNode = this.root;
|
|
57
46
|
|
|
58
|
-
while (x !==
|
|
47
|
+
while (x !== SN) {
|
|
59
48
|
y = x;
|
|
60
49
|
if (node.key < x.key) {
|
|
61
50
|
x = x.left;
|
|
@@ -94,10 +83,9 @@ export class RedBlackTree {
|
|
|
94
83
|
*/
|
|
95
84
|
delete(key: number): void {
|
|
96
85
|
const helper = (node: RBTreeNode): void => {
|
|
97
|
-
|
|
98
|
-
let z: RBTreeNode = this.NIL;
|
|
86
|
+
let z: RBTreeNode = SN;
|
|
99
87
|
let x: RBTreeNode, y: RBTreeNode;
|
|
100
|
-
while (node !==
|
|
88
|
+
while (node !== SN) {
|
|
101
89
|
if (node.key === key) {
|
|
102
90
|
z = node;
|
|
103
91
|
}
|
|
@@ -109,17 +97,16 @@ export class RedBlackTree {
|
|
|
109
97
|
}
|
|
110
98
|
}
|
|
111
99
|
|
|
112
|
-
if (z ===
|
|
113
|
-
console.log("Couldn't find key in the tree");
|
|
100
|
+
if (z === SN) {
|
|
114
101
|
return;
|
|
115
102
|
}
|
|
116
103
|
|
|
117
104
|
y = z;
|
|
118
105
|
let yOriginalColor: number = y.color;
|
|
119
|
-
if (z.left ===
|
|
106
|
+
if (z.left === SN) {
|
|
120
107
|
x = z.right;
|
|
121
108
|
this._rbTransplant(z, z.right);
|
|
122
|
-
} else if (z.right ===
|
|
109
|
+
} else if (z.right === SN) {
|
|
123
110
|
x = z.left;
|
|
124
111
|
this._rbTransplant(z, z.left);
|
|
125
112
|
} else {
|
|
@@ -139,13 +126,17 @@ export class RedBlackTree {
|
|
|
139
126
|
y.left.parent = y;
|
|
140
127
|
y.color = z.color;
|
|
141
128
|
}
|
|
142
|
-
if (yOriginalColor ===
|
|
129
|
+
if (yOriginalColor === RBTNColor.BLACK) {
|
|
143
130
|
this._fixDelete(x);
|
|
144
131
|
}
|
|
145
|
-
}
|
|
132
|
+
};
|
|
146
133
|
helper(this.root);
|
|
147
134
|
}
|
|
148
135
|
|
|
136
|
+
isRealNode(node: RBTreeNode): node is RBTreeNode {
|
|
137
|
+
return node !== SN && node !== null;
|
|
138
|
+
}
|
|
139
|
+
|
|
149
140
|
/**
|
|
150
141
|
* The function `getNode` is a recursive depth-first search algorithm that searches for a node with a
|
|
151
142
|
* given key in a red-black tree.
|
|
@@ -158,40 +149,40 @@ export class RedBlackTree {
|
|
|
158
149
|
*/
|
|
159
150
|
getNode(key: number, beginRoot = this.root): RBTreeNode {
|
|
160
151
|
const dfs = (node: RBTreeNode): RBTreeNode => {
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
if (this.isRealNode(node)) {
|
|
153
|
+
if (key === node.key) {
|
|
154
|
+
return node;
|
|
155
|
+
}
|
|
164
156
|
|
|
165
|
-
|
|
166
|
-
return dfs(node.
|
|
157
|
+
if (key < node.key) return dfs(node.left);
|
|
158
|
+
return dfs(node.right);
|
|
159
|
+
} else {
|
|
160
|
+
return null as unknown as RBTreeNode;
|
|
167
161
|
}
|
|
168
|
-
|
|
169
|
-
}
|
|
162
|
+
};
|
|
170
163
|
return dfs(beginRoot);
|
|
171
164
|
}
|
|
172
165
|
|
|
173
|
-
|
|
174
166
|
/**
|
|
175
167
|
* The function returns the leftmost node in a red-black tree.
|
|
176
168
|
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode, which represents a node in
|
|
177
169
|
* a Red-Black Tree.
|
|
178
170
|
* @returns The leftmost node in the given RBTreeNode.
|
|
179
171
|
*/
|
|
180
|
-
getLeftMost(node: RBTreeNode): RBTreeNode {
|
|
181
|
-
while (node.left !== null && node.left !==
|
|
172
|
+
getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
|
|
173
|
+
while (node.left !== null && node.left !== SN) {
|
|
182
174
|
node = node.left;
|
|
183
175
|
}
|
|
184
176
|
return node;
|
|
185
177
|
}
|
|
186
178
|
|
|
187
|
-
|
|
188
179
|
/**
|
|
189
180
|
* The function returns the rightmost node in a red-black tree.
|
|
190
181
|
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
|
|
191
182
|
* @returns the rightmost node in a red-black tree.
|
|
192
183
|
*/
|
|
193
184
|
getRightMost(node: RBTreeNode): RBTreeNode {
|
|
194
|
-
while (node.right !== null && node.right !==
|
|
185
|
+
while (node.right !== null && node.right !== SN) {
|
|
195
186
|
node = node.right;
|
|
196
187
|
}
|
|
197
188
|
return node;
|
|
@@ -203,13 +194,12 @@ export class RedBlackTree {
|
|
|
203
194
|
* @returns the successor of the given RBTreeNode.
|
|
204
195
|
*/
|
|
205
196
|
getSuccessor(x: RBTreeNode): RBTreeNode {
|
|
206
|
-
|
|
207
|
-
if (x.right !== this.NIL) {
|
|
197
|
+
if (x.right !== SN) {
|
|
208
198
|
return this.getLeftMost(x.right);
|
|
209
199
|
}
|
|
210
200
|
|
|
211
201
|
let y: RBTreeNode = x.parent;
|
|
212
|
-
while (y !==
|
|
202
|
+
while (y !== SN && y !== null && x === y.right) {
|
|
213
203
|
x = y;
|
|
214
204
|
y = y.parent;
|
|
215
205
|
}
|
|
@@ -223,13 +213,12 @@ export class RedBlackTree {
|
|
|
223
213
|
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
224
214
|
*/
|
|
225
215
|
getPredecessor(x: RBTreeNode): RBTreeNode {
|
|
226
|
-
|
|
227
|
-
if (x.left !== this.NIL) {
|
|
216
|
+
if (x.left !== SN) {
|
|
228
217
|
return this.getRightMost(x.left);
|
|
229
218
|
}
|
|
230
219
|
|
|
231
220
|
let y: RBTreeNode = x.parent;
|
|
232
|
-
while (y !==
|
|
221
|
+
while (y !== SN && x === y.left) {
|
|
233
222
|
x = y;
|
|
234
223
|
y = y.parent;
|
|
235
224
|
}
|
|
@@ -244,7 +233,7 @@ export class RedBlackTree {
|
|
|
244
233
|
protected _leftRotate(x: RBTreeNode): void {
|
|
245
234
|
const y: RBTreeNode = x.right;
|
|
246
235
|
x.right = y.left;
|
|
247
|
-
if (y.left !==
|
|
236
|
+
if (y.left !== SN) {
|
|
248
237
|
y.left.parent = x;
|
|
249
238
|
}
|
|
250
239
|
y.parent = x.parent;
|
|
@@ -267,7 +256,7 @@ export class RedBlackTree {
|
|
|
267
256
|
protected _rightRotate(x: RBTreeNode): void {
|
|
268
257
|
const y: RBTreeNode = x.left;
|
|
269
258
|
x.left = y.right;
|
|
270
|
-
if (y.right !==
|
|
259
|
+
if (y.right !== SN) {
|
|
271
260
|
y.right.parent = x;
|
|
272
261
|
}
|
|
273
262
|
y.parent = x.parent;
|
|
@@ -289,24 +278,21 @@ export class RedBlackTree {
|
|
|
289
278
|
*/
|
|
290
279
|
protected _fixDelete(x: RBTreeNode): void {
|
|
291
280
|
let s: RBTreeNode;
|
|
292
|
-
while (x !== this.root && x.color ===
|
|
281
|
+
while (x !== this.root && x.color === RBTNColor.BLACK) {
|
|
293
282
|
if (x === x.parent.left) {
|
|
294
283
|
s = x.parent.right;
|
|
295
284
|
if (s.color === 1) {
|
|
296
|
-
|
|
297
285
|
s.color = RBTNColor.BLACK;
|
|
298
286
|
x.parent.color = RBTNColor.RED;
|
|
299
287
|
this._leftRotate(x.parent);
|
|
300
288
|
s = x.parent.right;
|
|
301
289
|
}
|
|
302
290
|
|
|
303
|
-
if (s.left.color ===
|
|
304
|
-
|
|
291
|
+
if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
305
292
|
s.color = RBTNColor.RED;
|
|
306
293
|
x = x.parent;
|
|
307
294
|
} else {
|
|
308
|
-
if (s.right.color ===
|
|
309
|
-
|
|
295
|
+
if (s.right.color === RBTNColor.BLACK) {
|
|
310
296
|
s.left.color = RBTNColor.BLACK;
|
|
311
297
|
s.color = RBTNColor.RED;
|
|
312
298
|
this._rightRotate(s);
|
|
@@ -322,20 +308,17 @@ export class RedBlackTree {
|
|
|
322
308
|
} else {
|
|
323
309
|
s = x.parent.left;
|
|
324
310
|
if (s.color === 1) {
|
|
325
|
-
|
|
326
311
|
s.color = RBTNColor.BLACK;
|
|
327
312
|
x.parent.color = RBTNColor.RED;
|
|
328
313
|
this._rightRotate(x.parent);
|
|
329
314
|
s = x.parent.left;
|
|
330
315
|
}
|
|
331
316
|
|
|
332
|
-
if (s.right.color ===
|
|
333
|
-
|
|
317
|
+
if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
334
318
|
s.color = RBTNColor.RED;
|
|
335
319
|
x = x.parent;
|
|
336
320
|
} else {
|
|
337
|
-
if (s.left.color ===
|
|
338
|
-
|
|
321
|
+
if (s.left.color === RBTNColor.BLACK) {
|
|
339
322
|
s.right.color = RBTNColor.BLACK;
|
|
340
323
|
s.color = RBTNColor.RED;
|
|
341
324
|
this._leftRotate(s);
|
|
@@ -380,14 +363,12 @@ export class RedBlackTree {
|
|
|
380
363
|
if (k.parent === k.parent.parent.right) {
|
|
381
364
|
u = k.parent.parent.left;
|
|
382
365
|
if (u.color === 1) {
|
|
383
|
-
|
|
384
366
|
u.color = RBTNColor.BLACK;
|
|
385
367
|
k.parent.color = RBTNColor.BLACK;
|
|
386
368
|
k.parent.parent.color = RBTNColor.RED;
|
|
387
369
|
k = k.parent.parent;
|
|
388
370
|
} else {
|
|
389
371
|
if (k === k.parent.left) {
|
|
390
|
-
|
|
391
372
|
k = k.parent;
|
|
392
373
|
this._rightRotate(k);
|
|
393
374
|
}
|
|
@@ -400,14 +381,12 @@ export class RedBlackTree {
|
|
|
400
381
|
u = k.parent.parent.right;
|
|
401
382
|
|
|
402
383
|
if (u.color === 1) {
|
|
403
|
-
|
|
404
384
|
u.color = RBTNColor.BLACK;
|
|
405
385
|
k.parent.color = RBTNColor.BLACK;
|
|
406
386
|
k.parent.parent.color = RBTNColor.RED;
|
|
407
387
|
k = k.parent.parent;
|
|
408
388
|
} else {
|
|
409
389
|
if (k === k.parent.right) {
|
|
410
|
-
|
|
411
390
|
k = k.parent;
|
|
412
391
|
this._leftRotate(k);
|
|
413
392
|
}
|
|
@@ -423,4 +402,4 @@ export class RedBlackTree {
|
|
|
423
402
|
}
|
|
424
403
|
this.root.color = RBTNColor.BLACK;
|
|
425
404
|
}
|
|
426
|
-
}
|
|
405
|
+
}
|
|
@@ -37,7 +37,8 @@ export class TreeMultisetNode<
|
|
|
37
37
|
*/
|
|
38
38
|
export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultisetNode<V, TreeMultisetNodeNested<V>>>
|
|
39
39
|
extends AVLTree<V, N>
|
|
40
|
-
implements IBinaryTree<V, N>
|
|
40
|
+
implements IBinaryTree<V, N>
|
|
41
|
+
{
|
|
41
42
|
/**
|
|
42
43
|
* The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to
|
|
43
44
|
* merge duplicated values.
|
|
@@ -169,7 +170,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
|
|
|
169
170
|
} else if (parent.right === undefined) {
|
|
170
171
|
parent.right = newNode;
|
|
171
172
|
if (newNode !== null) {
|
|
172
|
-
this._size =
|
|
173
|
+
this._size = this.size + 1;
|
|
173
174
|
this._setCount(this.count + newNode.count);
|
|
174
175
|
}
|
|
175
176
|
return parent.right;
|
|
@@ -282,7 +283,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
|
|
|
282
283
|
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
|
283
284
|
if (!this.root) return bstDeletedResult;
|
|
284
285
|
|
|
285
|
-
const curr: N | null = this.
|
|
286
|
+
const curr: N | null = this.getNode(identifier, callback);
|
|
286
287
|
if (!curr) return bstDeletedResult;
|
|
287
288
|
|
|
288
289
|
const parent: N | null = curr?.parent ? curr.parent : null;
|