tree-multimap-typed 2.1.2 → 2.2.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/dist/cjs/index.cjs +433 -193
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +4300 -0
- package/dist/cjs-legacy/index.cjs.map +1 -0
- package/dist/esm/index.mjs +433 -193
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +4289 -0
- package/dist/esm-legacy/index.mjs.map +1 -0
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +57 -3
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +65 -3
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +61 -5
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +58 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +59 -4
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +57 -3
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +66 -3
- package/dist/types/types/data-structures/base/base.d.ts +1 -1
- package/dist/umd/tree-multimap-typed.js +268 -26
- package/dist/umd/tree-multimap-typed.js.map +1 -1
- package/dist/umd/tree-multimap-typed.min.js +3 -3
- package/dist/umd/tree-multimap-typed.min.js.map +1 -1
- package/package.json +20 -2
- package/src/data-structures/base/iterable-entry-base.ts +4 -4
- package/src/data-structures/binary-tree/avl-tree-counter.ts +103 -12
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +116 -12
- package/src/data-structures/binary-tree/avl-tree.ts +109 -16
- package/src/data-structures/binary-tree/binary-tree.ts +3 -2
- package/src/data-structures/binary-tree/bst.ts +104 -12
- package/src/data-structures/binary-tree/red-black-tree.ts +110 -19
- package/src/data-structures/binary-tree/tree-counter.ts +102 -11
- package/src/data-structures/binary-tree/tree-multi-map.ts +124 -12
- package/src/data-structures/graph/abstract-graph.ts +8 -8
- package/src/data-structures/graph/directed-graph.ts +5 -5
- package/src/data-structures/graph/undirected-graph.ts +5 -5
- package/src/data-structures/hash/hash-map.ts +4 -4
- package/src/types/data-structures/base/base.ts +1 -1
- package/tsup.node.config.js +40 -6
|
@@ -203,6 +203,7 @@ export class BinaryTreeNode<K = any, V = any> {
|
|
|
203
203
|
* 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
|
|
204
204
|
* 4. Subtrees: Each child of a node forms the root of a subtree.
|
|
205
205
|
* 5. Leaf Nodes: Nodes without children are leaves.
|
|
206
|
+
*
|
|
206
207
|
* @example
|
|
207
208
|
* // determine loan approval using a decision tree
|
|
208
209
|
* // Decision tree structure
|
|
@@ -1673,7 +1674,7 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1673
1674
|
filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
|
|
1674
1675
|
const out = this._createInstance<K, V, R>();
|
|
1675
1676
|
let i = 0;
|
|
1676
|
-
for (const [k, v] of this) if (predicate.call(thisArg,
|
|
1677
|
+
for (const [k, v] of this) if (predicate.call(thisArg, v, k, i++, this)) out.add([k, v]);
|
|
1677
1678
|
return out;
|
|
1678
1679
|
}
|
|
1679
1680
|
|
|
@@ -1696,7 +1697,7 @@ export class BinaryTree<K = any, V = any, R = any>
|
|
|
1696
1697
|
): BinaryTree<MK, MV, MR> {
|
|
1697
1698
|
const out = this._createLike<MK, MV, MR>([], options);
|
|
1698
1699
|
let i = 0;
|
|
1699
|
-
for (const [k, v] of this) out.add(cb.call(thisArg,
|
|
1700
|
+
for (const [k, v] of this) out.add(cb.call(thisArg, v, k, i++, this));
|
|
1700
1701
|
return out;
|
|
1701
1702
|
}
|
|
1702
1703
|
|
|
@@ -16,12 +16,14 @@ import type {
|
|
|
16
16
|
CP,
|
|
17
17
|
DFSOrderPattern,
|
|
18
18
|
EntryCallback,
|
|
19
|
+
FamilyPosition,
|
|
19
20
|
IterationType,
|
|
20
21
|
NodeCallback,
|
|
21
22
|
NodePredicate,
|
|
22
|
-
OptNode
|
|
23
|
+
OptNode,
|
|
24
|
+
RBTNColor
|
|
23
25
|
} from '../../types';
|
|
24
|
-
import { BinaryTree
|
|
26
|
+
import { BinaryTree } from './binary-tree';
|
|
25
27
|
import { IBinaryTree } from '../../interfaces';
|
|
26
28
|
import { Queue } from '../queue';
|
|
27
29
|
import { isComparable } from '../../utils';
|
|
@@ -33,8 +35,10 @@ import { Range } from '../../common';
|
|
|
33
35
|
* @template K - The type of the key.
|
|
34
36
|
* @template V - The type of the value.
|
|
35
37
|
*/
|
|
36
|
-
export class BSTNode<K = any, V = any>
|
|
37
|
-
|
|
38
|
+
export class BSTNode<K = any, V = any> {
|
|
39
|
+
key: K;
|
|
40
|
+
value?: V;
|
|
41
|
+
parent?: BSTNode<K, V> = undefined;
|
|
38
42
|
|
|
39
43
|
/**
|
|
40
44
|
* Creates an instance of BSTNode.
|
|
@@ -44,10 +48,11 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
44
48
|
* @param [value] - The value associated with the key.
|
|
45
49
|
*/
|
|
46
50
|
constructor(key: K, value?: V) {
|
|
47
|
-
|
|
51
|
+
this.key = key;
|
|
52
|
+
this.value = value;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
_left?: BSTNode<K, V> | null | undefined = undefined;
|
|
51
56
|
|
|
52
57
|
/**
|
|
53
58
|
* Gets the left child of the node.
|
|
@@ -55,7 +60,7 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
55
60
|
*
|
|
56
61
|
* @returns The left child.
|
|
57
62
|
*/
|
|
58
|
-
|
|
63
|
+
get left(): BSTNode<K, V> | null | undefined {
|
|
59
64
|
return this._left;
|
|
60
65
|
}
|
|
61
66
|
|
|
@@ -65,12 +70,12 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
65
70
|
*
|
|
66
71
|
* @param v - The node to set as the left child.
|
|
67
72
|
*/
|
|
68
|
-
|
|
73
|
+
set left(v: BSTNode<K, V> | null | undefined) {
|
|
69
74
|
if (v) v.parent = this;
|
|
70
75
|
this._left = v;
|
|
71
76
|
}
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
_right?: BSTNode<K, V> | null | undefined = undefined;
|
|
74
79
|
|
|
75
80
|
/**
|
|
76
81
|
* Gets the right child of the node.
|
|
@@ -78,7 +83,7 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
78
83
|
*
|
|
79
84
|
* @returns The right child.
|
|
80
85
|
*/
|
|
81
|
-
|
|
86
|
+
get right(): BSTNode<K, V> | null | undefined {
|
|
82
87
|
return this._right;
|
|
83
88
|
}
|
|
84
89
|
|
|
@@ -88,10 +93,96 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
88
93
|
*
|
|
89
94
|
* @param v - The node to set as the right child.
|
|
90
95
|
*/
|
|
91
|
-
|
|
96
|
+
set right(v: BSTNode<K, V> | null | undefined) {
|
|
92
97
|
if (v) v.parent = this;
|
|
93
98
|
this._right = v;
|
|
94
99
|
}
|
|
100
|
+
|
|
101
|
+
_height: number = 0;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Gets the height of the node (used in self-balancing trees).
|
|
105
|
+
* @remarks Time O(1), Space O(1)
|
|
106
|
+
*
|
|
107
|
+
* @returns The height.
|
|
108
|
+
*/
|
|
109
|
+
get height(): number {
|
|
110
|
+
return this._height;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Sets the height of the node.
|
|
115
|
+
* @remarks Time O(1), Space O(1)
|
|
116
|
+
*
|
|
117
|
+
* @param value - The new height.
|
|
118
|
+
*/
|
|
119
|
+
set height(value: number) {
|
|
120
|
+
this._height = value;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
_color: RBTNColor = 'BLACK';
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Gets the color of the node (used in Red-Black trees).
|
|
127
|
+
* @remarks Time O(1), Space O(1)
|
|
128
|
+
*
|
|
129
|
+
* @returns The node's color.
|
|
130
|
+
*/
|
|
131
|
+
get color(): RBTNColor {
|
|
132
|
+
return this._color;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sets the color of the node.
|
|
137
|
+
* @remarks Time O(1), Space O(1)
|
|
138
|
+
*
|
|
139
|
+
* @param value - The new color.
|
|
140
|
+
*/
|
|
141
|
+
set color(value: RBTNColor) {
|
|
142
|
+
this._color = value;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
_count: number = 1;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
|
|
149
|
+
* @remarks Time O(1), Space O(1)
|
|
150
|
+
*
|
|
151
|
+
* @returns The subtree node count.
|
|
152
|
+
*/
|
|
153
|
+
get count(): number {
|
|
154
|
+
return this._count;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Sets the count of nodes in the subtree.
|
|
159
|
+
* @remarks Time O(1), Space O(1)
|
|
160
|
+
*
|
|
161
|
+
* @param value - The new count.
|
|
162
|
+
*/
|
|
163
|
+
set count(value: number) {
|
|
164
|
+
this._count = value;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Gets the position of the node relative to its parent.
|
|
169
|
+
* @remarks Time O(1), Space O(1)
|
|
170
|
+
*
|
|
171
|
+
* @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
|
|
172
|
+
*/
|
|
173
|
+
get familyPosition(): FamilyPosition {
|
|
174
|
+
if (!this.parent) {
|
|
175
|
+
return this.left || this.right ? 'ROOT' : 'ISOLATED';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (this.parent.left === this) {
|
|
179
|
+
return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
|
|
180
|
+
} else if (this.parent.right === this) {
|
|
181
|
+
return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return 'MAL_NODE';
|
|
185
|
+
}
|
|
95
186
|
}
|
|
96
187
|
|
|
97
188
|
/**
|
|
@@ -108,6 +199,7 @@ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
|
|
|
108
199
|
* 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
|
|
109
200
|
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
110
201
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
202
|
+
*
|
|
111
203
|
* @example
|
|
112
204
|
* // Merge 3 sorted datasets
|
|
113
205
|
* const dataset1 = new BST<number, string>([
|
|
@@ -817,7 +909,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
817
909
|
let index = 0;
|
|
818
910
|
// Iterates in-order
|
|
819
911
|
for (const [key, value] of this) {
|
|
820
|
-
out.add(callback.call(thisArg,
|
|
912
|
+
out.add(callback.call(thisArg, value, key, index++, this));
|
|
821
913
|
}
|
|
822
914
|
return out;
|
|
823
915
|
}
|
|
@@ -11,15 +11,18 @@ import type {
|
|
|
11
11
|
BinaryTreeOptions,
|
|
12
12
|
CRUD,
|
|
13
13
|
EntryCallback,
|
|
14
|
+
FamilyPosition,
|
|
14
15
|
OptNode,
|
|
15
16
|
RBTNColor,
|
|
16
17
|
RedBlackTreeOptions
|
|
17
18
|
} from '../../types';
|
|
18
|
-
import { BST
|
|
19
|
+
import { BST } from './bst';
|
|
19
20
|
import { IBinaryTree } from '../../interfaces';
|
|
20
21
|
|
|
21
|
-
export class RedBlackTreeNode<K = any, V = any>
|
|
22
|
-
|
|
22
|
+
export class RedBlackTreeNode<K = any, V = any> {
|
|
23
|
+
key: K;
|
|
24
|
+
value?: V;
|
|
25
|
+
parent?: RedBlackTreeNode<K, V> = undefined;
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
28
|
* Create a Red-Black Tree and optionally bulk-insert items.
|
|
@@ -31,11 +34,12 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
31
34
|
*/
|
|
32
35
|
|
|
33
36
|
constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {
|
|
34
|
-
|
|
35
|
-
this.
|
|
37
|
+
this.key = key;
|
|
38
|
+
this.value = value;
|
|
39
|
+
this.color = color;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
_left?: RedBlackTreeNode<K, V> | null | undefined = undefined;
|
|
39
43
|
|
|
40
44
|
/**
|
|
41
45
|
* Get the left child pointer.
|
|
@@ -43,7 +47,7 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
43
47
|
* @returns Left child node, or null/undefined.
|
|
44
48
|
*/
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
get left(): RedBlackTreeNode<K, V> | null | undefined {
|
|
47
51
|
return this._left;
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -54,14 +58,14 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
54
58
|
* @returns void
|
|
55
59
|
*/
|
|
56
60
|
|
|
57
|
-
|
|
61
|
+
set left(v: RedBlackTreeNode<K, V> | null | undefined) {
|
|
58
62
|
if (v) {
|
|
59
63
|
v.parent = this;
|
|
60
64
|
}
|
|
61
65
|
this._left = v;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
_right?: RedBlackTreeNode<K, V> | null | undefined = undefined;
|
|
65
69
|
|
|
66
70
|
/**
|
|
67
71
|
* Get the right child pointer.
|
|
@@ -69,7 +73,7 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
69
73
|
* @returns Right child node, or null/undefined.
|
|
70
74
|
*/
|
|
71
75
|
|
|
72
|
-
|
|
76
|
+
get right(): RedBlackTreeNode<K, V> | null | undefined {
|
|
73
77
|
return this._right;
|
|
74
78
|
}
|
|
75
79
|
|
|
@@ -80,12 +84,98 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
80
84
|
* @returns void
|
|
81
85
|
*/
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
set right(v: RedBlackTreeNode<K, V> | null | undefined) {
|
|
84
88
|
if (v) {
|
|
85
89
|
v.parent = this;
|
|
86
90
|
}
|
|
87
91
|
this._right = v;
|
|
88
92
|
}
|
|
93
|
+
|
|
94
|
+
_height: number = 0;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Gets the height of the node (used in self-balancing trees).
|
|
98
|
+
* @remarks Time O(1), Space O(1)
|
|
99
|
+
*
|
|
100
|
+
* @returns The height.
|
|
101
|
+
*/
|
|
102
|
+
get height(): number {
|
|
103
|
+
return this._height;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Sets the height of the node.
|
|
108
|
+
* @remarks Time O(1), Space O(1)
|
|
109
|
+
*
|
|
110
|
+
* @param value - The new height.
|
|
111
|
+
*/
|
|
112
|
+
set height(value: number) {
|
|
113
|
+
this._height = value;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_color: RBTNColor = 'BLACK';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Gets the color of the node (used in Red-Black trees).
|
|
120
|
+
* @remarks Time O(1), Space O(1)
|
|
121
|
+
*
|
|
122
|
+
* @returns The node's color.
|
|
123
|
+
*/
|
|
124
|
+
get color(): RBTNColor {
|
|
125
|
+
return this._color;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Sets the color of the node.
|
|
130
|
+
* @remarks Time O(1), Space O(1)
|
|
131
|
+
*
|
|
132
|
+
* @param value - The new color.
|
|
133
|
+
*/
|
|
134
|
+
set color(value: RBTNColor) {
|
|
135
|
+
this._color = value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_count: number = 1;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
|
|
142
|
+
* @remarks Time O(1), Space O(1)
|
|
143
|
+
*
|
|
144
|
+
* @returns The subtree node count.
|
|
145
|
+
*/
|
|
146
|
+
get count(): number {
|
|
147
|
+
return this._count;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Sets the count of nodes in the subtree.
|
|
152
|
+
* @remarks Time O(1), Space O(1)
|
|
153
|
+
*
|
|
154
|
+
* @param value - The new count.
|
|
155
|
+
*/
|
|
156
|
+
set count(value: number) {
|
|
157
|
+
this._count = value;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Gets the position of the node relative to its parent.
|
|
162
|
+
* @remarks Time O(1), Space O(1)
|
|
163
|
+
*
|
|
164
|
+
* @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
|
|
165
|
+
*/
|
|
166
|
+
get familyPosition(): FamilyPosition {
|
|
167
|
+
if (!this.parent) {
|
|
168
|
+
return this.left || this.right ? 'ROOT' : 'ISOLATED';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (this.parent.left === this) {
|
|
172
|
+
return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
|
|
173
|
+
} else if (this.parent.right === this) {
|
|
174
|
+
return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return 'MAL_NODE';
|
|
178
|
+
}
|
|
89
179
|
}
|
|
90
180
|
|
|
91
181
|
/**
|
|
@@ -94,8 +184,9 @@ export class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {
|
|
|
94
184
|
* @template K
|
|
95
185
|
* @template V
|
|
96
186
|
* @template R
|
|
97
|
-
* 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.
|
|
187
|
+
* 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high, but the query efficiency is slightly lower.
|
|
98
188
|
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
|
|
189
|
+
*
|
|
99
190
|
* @example
|
|
100
191
|
* // using Red-Black Tree as a price-based index for stock data
|
|
101
192
|
* // Define the structure of individual stock records
|
|
@@ -330,7 +421,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
330
421
|
|
|
331
422
|
let index = 0;
|
|
332
423
|
for (const [key, value] of this) {
|
|
333
|
-
out.add(callback.call(thisArg,
|
|
424
|
+
out.add(callback.call(thisArg, value, key, index++, this));
|
|
334
425
|
}
|
|
335
426
|
return out;
|
|
336
427
|
}
|
|
@@ -380,10 +471,10 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
380
471
|
*/
|
|
381
472
|
|
|
382
473
|
protected _insert(node: RedBlackTreeNode<K, V>): CRUD {
|
|
383
|
-
let current = this.root;
|
|
474
|
+
let current = this.root ?? this.NIL;
|
|
384
475
|
let parent: RedBlackTreeNode<K, V> | undefined = undefined;
|
|
385
476
|
|
|
386
|
-
while (this.
|
|
477
|
+
while (current !== this.NIL) {
|
|
387
478
|
parent = current;
|
|
388
479
|
const compared = this._compare(node.key, current.key);
|
|
389
480
|
if (compared < 0) {
|
|
@@ -459,7 +550,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
459
550
|
this._leftRotate(z);
|
|
460
551
|
}
|
|
461
552
|
|
|
462
|
-
if (z &&
|
|
553
|
+
if (z && z.parent && z.parent.parent) {
|
|
463
554
|
z.parent.color = 'BLACK';
|
|
464
555
|
z.parent.parent.color = 'RED';
|
|
465
556
|
this._rightRotate(z.parent.parent);
|
|
@@ -478,7 +569,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
478
569
|
this._rightRotate(z);
|
|
479
570
|
}
|
|
480
571
|
|
|
481
|
-
if (z &&
|
|
572
|
+
if (z && z.parent && z.parent.parent) {
|
|
482
573
|
z.parent.color = 'BLACK';
|
|
483
574
|
z.parent.parent.color = 'RED';
|
|
484
575
|
this._leftRotate(z.parent.parent);
|
|
@@ -575,7 +666,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
575
666
|
const y = x.right;
|
|
576
667
|
x.right = y.left;
|
|
577
668
|
|
|
578
|
-
if (
|
|
669
|
+
if (y.left && y.left !== this.NIL) {
|
|
579
670
|
y.left.parent = x;
|
|
580
671
|
}
|
|
581
672
|
|
|
@@ -608,7 +699,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
608
699
|
const x = y.left;
|
|
609
700
|
y.left = x.right;
|
|
610
701
|
|
|
611
|
-
if (
|
|
702
|
+
if (x.right && x.right !== this.NIL) {
|
|
612
703
|
x.right.parent = y;
|
|
613
704
|
}
|
|
614
705
|
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
BinaryTreeOptions,
|
|
12
12
|
BSTNOptKeyOrNode,
|
|
13
13
|
EntryCallback,
|
|
14
|
+
FamilyPosition,
|
|
14
15
|
IterationType,
|
|
15
16
|
OptNode,
|
|
16
17
|
RBTNColor,
|
|
@@ -19,7 +20,7 @@ import type {
|
|
|
19
20
|
import { BSTOptions } from '../../types';
|
|
20
21
|
import { BSTNode } from './bst';
|
|
21
22
|
import { IBinaryTree } from '../../interfaces';
|
|
22
|
-
import { RedBlackTree
|
|
23
|
+
import { RedBlackTree } from './red-black-tree';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* RB-tree node with an extra 'count' field; keeps parent/child links.
|
|
@@ -27,8 +28,10 @@ import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
|
|
|
27
28
|
* @template K
|
|
28
29
|
* @template V
|
|
29
30
|
*/
|
|
30
|
-
export class TreeCounterNode<K = any, V = any>
|
|
31
|
-
|
|
31
|
+
export class TreeCounterNode<K = any, V = any> {
|
|
32
|
+
key: K;
|
|
33
|
+
value?: V;
|
|
34
|
+
parent?: TreeCounterNode<K, V> = undefined;
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Create a tree counter node.
|
|
@@ -40,18 +43,20 @@ export class TreeCounterNode<K = any, V = any> extends RedBlackTreeNode<K, V> {
|
|
|
40
43
|
* @returns New TreeCounterNode instance.
|
|
41
44
|
*/
|
|
42
45
|
constructor(key: K, value?: V, count = 1, color: RBTNColor = 'BLACK') {
|
|
43
|
-
|
|
46
|
+
this.key = key;
|
|
47
|
+
this.value = value;
|
|
48
|
+
this.color = color;
|
|
44
49
|
this.count = count;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
_left?: TreeCounterNode<K, V> | null | undefined = undefined;
|
|
48
53
|
|
|
49
54
|
/**
|
|
50
55
|
* Get the left child pointer.
|
|
51
56
|
* @remarks Time O(1), Space O(1)
|
|
52
57
|
* @returns Left child node, or null/undefined.
|
|
53
58
|
*/
|
|
54
|
-
|
|
59
|
+
get left(): TreeCounterNode<K, V> | null | undefined {
|
|
55
60
|
return this._left;
|
|
56
61
|
}
|
|
57
62
|
|
|
@@ -61,21 +66,21 @@ export class TreeCounterNode<K = any, V = any> extends RedBlackTreeNode<K, V> {
|
|
|
61
66
|
* @param v - New left child node, or null/undefined.
|
|
62
67
|
* @returns void
|
|
63
68
|
*/
|
|
64
|
-
|
|
69
|
+
set left(v: TreeCounterNode<K, V> | null | undefined) {
|
|
65
70
|
if (v) {
|
|
66
71
|
v.parent = this;
|
|
67
72
|
}
|
|
68
73
|
this._left = v;
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
_right?: TreeCounterNode<K, V> | null | undefined = undefined;
|
|
72
77
|
|
|
73
78
|
/**
|
|
74
79
|
* Get the right child pointer.
|
|
75
80
|
* @remarks Time O(1), Space O(1)
|
|
76
81
|
* @returns Right child node, or null/undefined.
|
|
77
82
|
*/
|
|
78
|
-
|
|
83
|
+
get right(): TreeCounterNode<K, V> | null | undefined {
|
|
79
84
|
return this._right;
|
|
80
85
|
}
|
|
81
86
|
|
|
@@ -85,12 +90,98 @@ export class TreeCounterNode<K = any, V = any> extends RedBlackTreeNode<K, V> {
|
|
|
85
90
|
* @param v - New right child node, or null/undefined.
|
|
86
91
|
* @returns void
|
|
87
92
|
*/
|
|
88
|
-
|
|
93
|
+
set right(v: TreeCounterNode<K, V> | null | undefined) {
|
|
89
94
|
if (v) {
|
|
90
95
|
v.parent = this;
|
|
91
96
|
}
|
|
92
97
|
this._right = v;
|
|
93
98
|
}
|
|
99
|
+
|
|
100
|
+
_height: number = 0;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Gets the height of the node (used in self-balancing trees).
|
|
104
|
+
* @remarks Time O(1), Space O(1)
|
|
105
|
+
*
|
|
106
|
+
* @returns The height.
|
|
107
|
+
*/
|
|
108
|
+
get height(): number {
|
|
109
|
+
return this._height;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Sets the height of the node.
|
|
114
|
+
* @remarks Time O(1), Space O(1)
|
|
115
|
+
*
|
|
116
|
+
* @param value - The new height.
|
|
117
|
+
*/
|
|
118
|
+
set height(value: number) {
|
|
119
|
+
this._height = value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
_color: RBTNColor = 'BLACK';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Gets the color of the node (used in Red-Black trees).
|
|
126
|
+
* @remarks Time O(1), Space O(1)
|
|
127
|
+
*
|
|
128
|
+
* @returns The node's color.
|
|
129
|
+
*/
|
|
130
|
+
get color(): RBTNColor {
|
|
131
|
+
return this._color;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Sets the color of the node.
|
|
136
|
+
* @remarks Time O(1), Space O(1)
|
|
137
|
+
*
|
|
138
|
+
* @param value - The new color.
|
|
139
|
+
*/
|
|
140
|
+
set color(value: RBTNColor) {
|
|
141
|
+
this._color = value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_count: number = 1;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
|
|
148
|
+
* @remarks Time O(1), Space O(1)
|
|
149
|
+
*
|
|
150
|
+
* @returns The subtree node count.
|
|
151
|
+
*/
|
|
152
|
+
get count(): number {
|
|
153
|
+
return this._count;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Sets the count of nodes in the subtree.
|
|
158
|
+
* @remarks Time O(1), Space O(1)
|
|
159
|
+
*
|
|
160
|
+
* @param value - The new count.
|
|
161
|
+
*/
|
|
162
|
+
set count(value: number) {
|
|
163
|
+
this._count = value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Gets the position of the node relative to its parent.
|
|
168
|
+
* @remarks Time O(1), Space O(1)
|
|
169
|
+
*
|
|
170
|
+
* @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
|
|
171
|
+
*/
|
|
172
|
+
get familyPosition(): FamilyPosition {
|
|
173
|
+
if (!this.parent) {
|
|
174
|
+
return this.left || this.right ? 'ROOT' : 'ISOLATED';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (this.parent.left === this) {
|
|
178
|
+
return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
|
|
179
|
+
} else if (this.parent.right === this) {
|
|
180
|
+
return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return 'MAL_NODE';
|
|
184
|
+
}
|
|
94
185
|
}
|
|
95
186
|
|
|
96
187
|
/**
|
|
@@ -348,7 +439,7 @@ export class TreeCounter<K = any, V = any, R = any> extends RedBlackTree<K, V, R
|
|
|
348
439
|
|
|
349
440
|
let index = 0;
|
|
350
441
|
for (const [key, value] of this) {
|
|
351
|
-
out.add(callback.call(thisArg,
|
|
442
|
+
out.add(callback.call(thisArg, value, key, index++, this));
|
|
352
443
|
}
|
|
353
444
|
return out;
|
|
354
445
|
}
|