min-heap-typed 1.42.3 → 1.42.4
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/binary-tree/avl-tree.d.ts +2 -2
- package/dist/data-structures/binary-tree/avl-tree.js +5 -3
- package/dist/data-structures/binary-tree/binary-tree.d.ts +56 -52
- package/dist/data-structures/binary-tree/binary-tree.js +115 -53
- package/dist/data-structures/binary-tree/bst.d.ts +42 -15
- package/dist/data-structures/binary-tree/bst.js +77 -21
- package/dist/data-structures/binary-tree/rb-tree.d.ts +28 -51
- package/dist/data-structures/binary-tree/rb-tree.js +148 -180
- package/dist/data-structures/binary-tree/tree-multiset.d.ts +10 -10
- package/dist/data-structures/binary-tree/tree-multiset.js +20 -17
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.js +0 -5
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +5 -4
- package/src/data-structures/binary-tree/binary-tree.ts +201 -131
- package/src/data-structures/binary-tree/bst.ts +100 -34
- package/src/data-structures/binary-tree/rb-tree.ts +227 -236
- package/src/data-structures/binary-tree/tree-multiset.ts +24 -23
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +5 -5
|
@@ -6,26 +6,27 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
import {
|
|
10
|
+
BinaryTreeDeletedResult,
|
|
11
|
+
BTNCallback,
|
|
12
|
+
BTNKey,
|
|
13
|
+
IterationType,
|
|
14
|
+
RBTNColor,
|
|
15
|
+
RBTreeNodeNested,
|
|
16
|
+
RBTreeOptions
|
|
17
|
+
} from '../../types';
|
|
18
|
+
import {BST, BSTNode} from "./bst";
|
|
19
|
+
import {IBinaryTree} from "../../interfaces";
|
|
20
|
+
import {BinaryTreeNode} from "./binary-tree";
|
|
21
|
+
|
|
22
|
+
export class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V>> extends BSTNode<V, N> {
|
|
23
|
+
color: RBTNColor;
|
|
24
|
+
constructor(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK) {
|
|
25
|
+
super(key, value);
|
|
20
26
|
this.color = color;
|
|
21
|
-
this.parent = null as unknown as RBTreeNode;
|
|
22
|
-
this.left = null as unknown as RBTreeNode;
|
|
23
|
-
this.right = null as unknown as RBTreeNode;
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export const NIL = new RBTreeNode(0);
|
|
28
|
-
|
|
29
30
|
/**
|
|
30
31
|
* 1. Each node is either red or black.
|
|
31
32
|
* 2. The root node is always black.
|
|
@@ -33,14 +34,19 @@ export const NIL = new RBTreeNode(0);
|
|
|
33
34
|
* 4. Red nodes must have black children.
|
|
34
35
|
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
35
36
|
*/
|
|
36
|
-
export class RedBlackTree
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNested<V>>>
|
|
38
|
+
extends BST<V, N>
|
|
39
|
+
implements IBinaryTree<V, N>
|
|
40
|
+
{
|
|
41
|
+
|
|
42
|
+
constructor(options?: RBTreeOptions) {
|
|
43
|
+
super(options);
|
|
44
|
+
this._root = this.NIL;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
protected _root:
|
|
47
|
+
protected _root: N;
|
|
42
48
|
|
|
43
|
-
get root():
|
|
49
|
+
get root(): N {
|
|
44
50
|
return this._root;
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -50,46 +56,53 @@ export class RedBlackTree {
|
|
|
50
56
|
return this._size;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
55
|
-
* violations of the red-black tree properties.
|
|
56
|
-
* @param {number} key - The key parameter is a number that represents the value to be inserted into
|
|
57
|
-
* the RBTree.
|
|
58
|
-
* @returns The function does not explicitly return anything.
|
|
59
|
-
*/
|
|
60
|
-
add(key: number): void {
|
|
61
|
-
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
62
|
-
node.left = NIL;
|
|
63
|
-
node.right = NIL;
|
|
59
|
+
NIL: N = new RBTreeNode<V>(NaN) as unknown as N;
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
let
|
|
61
|
+
override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
|
|
62
|
+
let node: N;
|
|
63
|
+
if (typeof keyOrNode === 'number') {
|
|
64
|
+
node = this.createNode(keyOrNode, value, RBTNColor.RED);
|
|
65
|
+
} else if(keyOrNode instanceof RBTreeNode) {
|
|
66
|
+
node = keyOrNode;
|
|
67
|
+
} else if (keyOrNode === null) {
|
|
68
|
+
return;
|
|
69
|
+
} else if (keyOrNode === undefined) {
|
|
70
|
+
return;
|
|
71
|
+
} else {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
node.left = this.NIL;
|
|
76
|
+
node.right = this.NIL;
|
|
77
|
+
|
|
78
|
+
let y: N | undefined = undefined;
|
|
79
|
+
let x: N | undefined = this.root;
|
|
67
80
|
|
|
68
|
-
while (x !== NIL) {
|
|
81
|
+
while (x !== this.NIL) {
|
|
69
82
|
y = x;
|
|
70
|
-
if (node.key < x.key) {
|
|
83
|
+
if (x && node.key < x.key) {
|
|
71
84
|
x = x.left;
|
|
72
85
|
} else {
|
|
73
|
-
x = x
|
|
86
|
+
x = x?.right;
|
|
74
87
|
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
node.parent = y;
|
|
78
|
-
if (y ===
|
|
79
|
-
this.
|
|
91
|
+
if (y === undefined) {
|
|
92
|
+
this._setRoot(node);
|
|
80
93
|
} else if (node.key < y.key) {
|
|
81
94
|
y.left = node;
|
|
82
95
|
} else {
|
|
83
96
|
y.right = node;
|
|
84
97
|
}
|
|
85
98
|
|
|
86
|
-
if (node.parent ===
|
|
99
|
+
if (node.parent === undefined) {
|
|
87
100
|
node.color = RBTNColor.BLACK;
|
|
88
101
|
this._size++;
|
|
89
102
|
return;
|
|
90
103
|
}
|
|
91
104
|
|
|
92
|
-
if (node.parent.parent ===
|
|
105
|
+
if (node.parent.parent === undefined) {
|
|
93
106
|
this._size++;
|
|
94
107
|
return;
|
|
95
108
|
}
|
|
@@ -98,95 +111,121 @@ export class RedBlackTree {
|
|
|
98
111
|
this._size++;
|
|
99
112
|
}
|
|
100
113
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
|
|
115
|
+
return new RBTreeNode<V, N>(key, value, color) as N;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
delete<C extends BTNCallback<N>>(
|
|
120
|
+
identifier: ReturnType<C> | null | undefined,
|
|
121
|
+
callback: C = this.defaultOneParamCallback as C
|
|
122
|
+
): BinaryTreeDeletedResult<N>[] {
|
|
123
|
+
const ans: BinaryTreeDeletedResult<N>[] = [];
|
|
124
|
+
if (identifier === null) return ans;
|
|
125
|
+
const helper = (node: N | undefined): void => {
|
|
126
|
+
let z: N = this.NIL;
|
|
127
|
+
let x: N | undefined, y: N;
|
|
128
|
+
while (node !== this.NIL) {
|
|
129
|
+
if (node && callback(node) === identifier) {
|
|
114
130
|
z = node;
|
|
115
131
|
}
|
|
116
132
|
|
|
117
|
-
if (node
|
|
133
|
+
if (node && identifier && callback(node) <= identifier) {
|
|
118
134
|
node = node.right;
|
|
119
135
|
} else {
|
|
120
|
-
node = node
|
|
136
|
+
node = node?.left;
|
|
121
137
|
}
|
|
122
138
|
}
|
|
123
139
|
|
|
124
|
-
if (z === NIL) {
|
|
140
|
+
if (z === this.NIL) {
|
|
125
141
|
this._size--;
|
|
126
142
|
return;
|
|
127
143
|
}
|
|
128
144
|
|
|
129
145
|
y = z;
|
|
130
146
|
let yOriginalColor: number = y.color;
|
|
131
|
-
if (z.left === NIL) {
|
|
147
|
+
if (z.left === this.NIL) {
|
|
132
148
|
x = z.right;
|
|
133
|
-
this._rbTransplant(z, z.right);
|
|
134
|
-
} else if (z.right === NIL) {
|
|
149
|
+
this._rbTransplant(z, z.right!);
|
|
150
|
+
} else if (z.right === this.NIL) {
|
|
135
151
|
x = z.left;
|
|
136
|
-
this._rbTransplant(z, z.left);
|
|
152
|
+
this._rbTransplant(z, z.left!);
|
|
137
153
|
} else {
|
|
138
154
|
y = this.getLeftMost(z.right);
|
|
139
155
|
yOriginalColor = y.color;
|
|
140
156
|
x = y.right;
|
|
141
157
|
if (y.parent === z) {
|
|
142
|
-
x
|
|
158
|
+
x!.parent = y;
|
|
143
159
|
} else {
|
|
144
|
-
this._rbTransplant(y, y.right);
|
|
160
|
+
this._rbTransplant(y, y.right!);
|
|
145
161
|
y.right = z.right;
|
|
146
|
-
y.right
|
|
162
|
+
y.right!.parent = y;
|
|
147
163
|
}
|
|
148
164
|
|
|
149
165
|
this._rbTransplant(z, y);
|
|
150
166
|
y.left = z.left;
|
|
151
|
-
y.left
|
|
167
|
+
y.left!.parent = y;
|
|
152
168
|
y.color = z.color;
|
|
153
169
|
}
|
|
154
170
|
if (yOriginalColor === RBTNColor.BLACK) {
|
|
155
|
-
this._fixDelete(x);
|
|
171
|
+
this._fixDelete(x!);
|
|
156
172
|
}
|
|
157
173
|
this._size--;
|
|
158
174
|
};
|
|
159
175
|
helper(this.root);
|
|
176
|
+
// TODO
|
|
177
|
+
return ans;
|
|
160
178
|
}
|
|
161
179
|
|
|
162
|
-
|
|
163
|
-
return node !== NIL && node !==
|
|
180
|
+
isNode(node: N | undefined): node is N {
|
|
181
|
+
return node !== this.NIL && node !== undefined;
|
|
164
182
|
}
|
|
165
183
|
|
|
184
|
+
getNode<C extends BTNCallback<N, BTNKey>>(
|
|
185
|
+
identifier: BTNKey,
|
|
186
|
+
callback?: C,
|
|
187
|
+
beginRoot?: N | undefined,
|
|
188
|
+
iterationType?: IterationType
|
|
189
|
+
): N | undefined;
|
|
190
|
+
|
|
191
|
+
getNode<C extends BTNCallback<N, N>>(
|
|
192
|
+
identifier: N | undefined,
|
|
193
|
+
callback?: C,
|
|
194
|
+
beginRoot?: N | undefined,
|
|
195
|
+
iterationType?: IterationType
|
|
196
|
+
): N | undefined;
|
|
197
|
+
|
|
198
|
+
getNode<C extends BTNCallback<N>>(
|
|
199
|
+
identifier: ReturnType<C>,
|
|
200
|
+
callback: C,
|
|
201
|
+
beginRoot?: N | undefined,
|
|
202
|
+
iterationType?: IterationType
|
|
203
|
+
): N | undefined;
|
|
204
|
+
|
|
166
205
|
/**
|
|
167
|
-
* The function `
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* @param
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
206
|
+
* The function `get` returns the first node in a binary tree that matches the given property or key.
|
|
207
|
+
* @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
|
|
208
|
+
* the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`
|
|
209
|
+
* type.
|
|
210
|
+
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
211
|
+
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
212
|
+
* whether the node matches the criteria or not. The default callback function
|
|
213
|
+
* (`this.defaultOneParamCallback`) is used if no callback function is
|
|
214
|
+
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
215
|
+
* the root node from which the search should begin.
|
|
216
|
+
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
217
|
+
* performed when searching for a node in the binary tree. It can have one of the following values:
|
|
218
|
+
* @returns either the found node (of type N) or null if no node is found.
|
|
175
219
|
*/
|
|
176
|
-
getNode
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
} else {
|
|
186
|
-
return null as unknown as RBTreeNode;
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
return dfs(beginRoot);
|
|
220
|
+
getNode<C extends BTNCallback<N>>(
|
|
221
|
+
identifier: ReturnType<C> | undefined,
|
|
222
|
+
callback: C = this.defaultOneParamCallback as C,
|
|
223
|
+
beginRoot = this.root,
|
|
224
|
+
iterationType = this.iterationType
|
|
225
|
+
): N | null | undefined {
|
|
226
|
+
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
227
|
+
|
|
228
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
190
229
|
}
|
|
191
230
|
|
|
192
231
|
/**
|
|
@@ -195,8 +234,8 @@ export class RedBlackTree {
|
|
|
195
234
|
* a Red-Black Tree.
|
|
196
235
|
* @returns The leftmost node in the given RBTreeNode.
|
|
197
236
|
*/
|
|
198
|
-
getLeftMost(node:
|
|
199
|
-
while (node.left !==
|
|
237
|
+
getLeftMost(node: N = this.root): N {
|
|
238
|
+
while (node.left !== undefined && node.left !== this.NIL) {
|
|
200
239
|
node = node.left;
|
|
201
240
|
}
|
|
202
241
|
return node;
|
|
@@ -207,8 +246,8 @@ export class RedBlackTree {
|
|
|
207
246
|
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
|
|
208
247
|
* @returns the rightmost node in a red-black tree.
|
|
209
248
|
*/
|
|
210
|
-
getRightMost(node:
|
|
211
|
-
while (node.right !==
|
|
249
|
+
getRightMost(node: N): N {
|
|
250
|
+
while (node.right !== undefined && node.right !== this.NIL) {
|
|
212
251
|
node = node.right;
|
|
213
252
|
}
|
|
214
253
|
return node;
|
|
@@ -219,13 +258,13 @@ export class RedBlackTree {
|
|
|
219
258
|
* @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.
|
|
220
259
|
* @returns the successor of the given RBTreeNode.
|
|
221
260
|
*/
|
|
222
|
-
getSuccessor(x:
|
|
223
|
-
if (x.right !== NIL) {
|
|
261
|
+
getSuccessor(x: N): N | undefined {
|
|
262
|
+
if (x.right !== this.NIL) {
|
|
224
263
|
return this.getLeftMost(x.right);
|
|
225
264
|
}
|
|
226
265
|
|
|
227
|
-
let y:
|
|
228
|
-
while (y !== NIL && y !==
|
|
266
|
+
let y: N | undefined = x.parent;
|
|
267
|
+
while (y !== this.NIL && y !== undefined && x === y.right) {
|
|
229
268
|
x = y;
|
|
230
269
|
y = y.parent;
|
|
231
270
|
}
|
|
@@ -238,104 +277,54 @@ export class RedBlackTree {
|
|
|
238
277
|
* Red-Black Tree.
|
|
239
278
|
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
240
279
|
*/
|
|
241
|
-
getPredecessor(x:
|
|
242
|
-
if (x.left !== NIL) {
|
|
243
|
-
return this.getRightMost(x.left);
|
|
280
|
+
getPredecessor(x: N): N {
|
|
281
|
+
if (x.left !== this.NIL) {
|
|
282
|
+
return this.getRightMost(x.left!);
|
|
244
283
|
}
|
|
245
284
|
|
|
246
|
-
let y:
|
|
247
|
-
while (y !== NIL && x === y
|
|
248
|
-
x = y
|
|
249
|
-
y = y
|
|
285
|
+
let y: N | undefined = x.parent;
|
|
286
|
+
while (y !== this.NIL && x === y!.left) {
|
|
287
|
+
x = y!;
|
|
288
|
+
y = y!.parent;
|
|
250
289
|
}
|
|
251
290
|
|
|
252
|
-
return y
|
|
291
|
+
return y!;
|
|
253
292
|
}
|
|
254
293
|
|
|
255
|
-
clear() {
|
|
256
|
-
this._root = NIL;
|
|
294
|
+
override clear() {
|
|
295
|
+
this._root = this.NIL;
|
|
257
296
|
this._size = 0;
|
|
258
297
|
}
|
|
259
298
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const _displayAux = (node: RBTreeNode | null): [string[], number, number, number] => {
|
|
269
|
-
if (node === null) {
|
|
270
|
-
return [[], 0, 0, 0];
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (node.right === null && node.left === null) {
|
|
274
|
-
const line = `${node.key}`;
|
|
275
|
-
const width = line.length;
|
|
276
|
-
const height = 1;
|
|
277
|
-
const middle = Math.floor(width / 2);
|
|
278
|
-
return [[line], width, height, middle];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (node.right === null) {
|
|
282
|
-
const [lines, n, p, x] = _displayAux(node.left);
|
|
283
|
-
const s = `${node.key}`;
|
|
284
|
-
const u = s.length;
|
|
285
|
-
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
|
|
286
|
-
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
|
|
287
|
-
const shifted_lines = lines.map(line => line + ' '.repeat(u));
|
|
288
|
-
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (node.left === null) {
|
|
292
|
-
const [lines, n, p, u] = _displayAux(node.right);
|
|
293
|
-
const s = `${node.key}`;
|
|
294
|
-
const x = s.length;
|
|
295
|
-
const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
|
|
296
|
-
const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
|
|
297
|
-
const shifted_lines = lines.map(line => ' '.repeat(u) + line);
|
|
298
|
-
return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const [left, n, p, x] = _displayAux(node.left);
|
|
302
|
-
const [right, m, q, y] = _displayAux(node.right);
|
|
303
|
-
const s = `${node.key}`;
|
|
304
|
-
const u = s.length;
|
|
305
|
-
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
|
|
306
|
-
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
|
|
307
|
-
if (p < q) {
|
|
308
|
-
left.push(...new Array(q - p).fill(' '.repeat(n)));
|
|
309
|
-
} else if (q < p) {
|
|
310
|
-
right.push(...new Array(p - q).fill(' '.repeat(m)));
|
|
311
|
-
}
|
|
312
|
-
const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
|
|
313
|
-
return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
display(beginRoot);
|
|
299
|
+
protected override _setRoot(v: N) {
|
|
300
|
+
if (v) {
|
|
301
|
+
v.parent = undefined;
|
|
302
|
+
}
|
|
303
|
+
this._root = v;
|
|
317
304
|
}
|
|
318
305
|
|
|
319
306
|
/**
|
|
320
307
|
* The function performs a left rotation on a red-black tree node.
|
|
321
308
|
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
|
322
309
|
*/
|
|
323
|
-
protected _leftRotate(x:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
y.left.
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
x.parent.left
|
|
334
|
-
|
|
335
|
-
|
|
310
|
+
protected _leftRotate(x: N): void {
|
|
311
|
+
if (x.right) {
|
|
312
|
+
const y: N = x.right;
|
|
313
|
+
x.right = y.left;
|
|
314
|
+
if (y.left !== this.NIL) {
|
|
315
|
+
if (y.left) y.left.parent = x;
|
|
316
|
+
}
|
|
317
|
+
y.parent = x.parent;
|
|
318
|
+
if (x.parent === undefined) {
|
|
319
|
+
this._setRoot(y);
|
|
320
|
+
} else if (x === x.parent.left) {
|
|
321
|
+
x.parent.left = y;
|
|
322
|
+
} else {
|
|
323
|
+
x.parent.right = y;
|
|
324
|
+
}
|
|
325
|
+
y.left = x;
|
|
326
|
+
x.parent = y;
|
|
336
327
|
}
|
|
337
|
-
y.left = x;
|
|
338
|
-
x.parent = y;
|
|
339
328
|
}
|
|
340
329
|
|
|
341
330
|
/**
|
|
@@ -343,22 +332,24 @@ export class RedBlackTree {
|
|
|
343
332
|
* @param {RBTreeNode} x - x is a RBTreeNode, which represents the node that needs to be right
|
|
344
333
|
* rotated.
|
|
345
334
|
*/
|
|
346
|
-
protected _rightRotate(x:
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
y.right.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
x.parent.right
|
|
357
|
-
|
|
358
|
-
|
|
335
|
+
protected _rightRotate(x: N): void {
|
|
336
|
+
if (x.left) {
|
|
337
|
+
const y: N = x.left;
|
|
338
|
+
x.left = y.right;
|
|
339
|
+
if (y.right !== this.NIL) {
|
|
340
|
+
if (y.right) y.right.parent = x;
|
|
341
|
+
}
|
|
342
|
+
y.parent = x.parent;
|
|
343
|
+
if (x.parent === undefined) {
|
|
344
|
+
this._setRoot(y);
|
|
345
|
+
} else if (x === x.parent.right) {
|
|
346
|
+
x.parent.right = y;
|
|
347
|
+
} else {
|
|
348
|
+
x.parent.left = y;
|
|
349
|
+
}
|
|
350
|
+
y.right = x;
|
|
351
|
+
x.parent = y;
|
|
359
352
|
}
|
|
360
|
-
y.right = x;
|
|
361
|
-
x.parent = y;
|
|
362
353
|
}
|
|
363
354
|
|
|
364
355
|
/**
|
|
@@ -366,59 +357,59 @@ export class RedBlackTree {
|
|
|
366
357
|
* @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a
|
|
367
358
|
* red-black tree.
|
|
368
359
|
*/
|
|
369
|
-
protected _fixDelete(x:
|
|
370
|
-
let s:
|
|
360
|
+
protected _fixDelete(x: N): void {
|
|
361
|
+
let s: N | undefined;
|
|
371
362
|
while (x !== this.root && x.color === RBTNColor.BLACK) {
|
|
372
|
-
if (x === x.parent.left) {
|
|
373
|
-
s = x.parent.right
|
|
363
|
+
if (x.parent && x === x.parent.left) {
|
|
364
|
+
s = x.parent.right!;
|
|
374
365
|
if (s.color === 1) {
|
|
375
366
|
s.color = RBTNColor.BLACK;
|
|
376
367
|
x.parent.color = RBTNColor.RED;
|
|
377
368
|
this._leftRotate(x.parent);
|
|
378
|
-
s = x.parent.right
|
|
369
|
+
s = x.parent.right!;
|
|
379
370
|
}
|
|
380
371
|
|
|
381
|
-
if (s.left !==
|
|
372
|
+
if (s.left !== undefined && s.left.color === RBTNColor.BLACK && s.right && s.right.color === RBTNColor.BLACK) {
|
|
382
373
|
s.color = RBTNColor.RED;
|
|
383
374
|
x = x.parent;
|
|
384
375
|
} else {
|
|
385
|
-
if (s.right.color === RBTNColor.BLACK) {
|
|
386
|
-
s.left.color = RBTNColor.BLACK;
|
|
376
|
+
if (s.right && s.right.color === RBTNColor.BLACK) {
|
|
377
|
+
if (s.left) s.left.color = RBTNColor.BLACK;
|
|
387
378
|
s.color = RBTNColor.RED;
|
|
388
379
|
this._rightRotate(s);
|
|
389
380
|
s = x.parent.right;
|
|
390
381
|
}
|
|
391
382
|
|
|
392
|
-
s.color = x.parent.color;
|
|
383
|
+
if (s) s.color = x.parent.color;
|
|
393
384
|
x.parent.color = RBTNColor.BLACK;
|
|
394
|
-
s.right.color = RBTNColor.BLACK;
|
|
385
|
+
if (s && s.right) s.right.color = RBTNColor.BLACK;
|
|
395
386
|
this._leftRotate(x.parent);
|
|
396
387
|
x = this.root;
|
|
397
388
|
}
|
|
398
389
|
} else {
|
|
399
|
-
s = x.parent
|
|
390
|
+
s = x.parent!.left!;
|
|
400
391
|
if (s.color === 1) {
|
|
401
392
|
s.color = RBTNColor.BLACK;
|
|
402
|
-
x.parent
|
|
403
|
-
this._rightRotate(x.parent);
|
|
404
|
-
s = x.parent
|
|
393
|
+
x.parent!.color = RBTNColor.RED;
|
|
394
|
+
this._rightRotate(x.parent!);
|
|
395
|
+
s = x.parent!.left;
|
|
405
396
|
}
|
|
406
397
|
|
|
407
|
-
if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
398
|
+
if (s && s.right && s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
408
399
|
s.color = RBTNColor.RED;
|
|
409
|
-
x = x.parent
|
|
400
|
+
x = x.parent!;
|
|
410
401
|
} else {
|
|
411
|
-
if (s.left.color === RBTNColor.BLACK) {
|
|
412
|
-
s.right.color = RBTNColor.BLACK;
|
|
402
|
+
if (s && s.left && s.left.color === RBTNColor.BLACK) {
|
|
403
|
+
if (s.right) s.right.color = RBTNColor.BLACK;
|
|
413
404
|
s.color = RBTNColor.RED;
|
|
414
405
|
this._leftRotate(s);
|
|
415
|
-
s = x.parent
|
|
406
|
+
s = x.parent!.left;
|
|
416
407
|
}
|
|
417
408
|
|
|
418
|
-
s.color = x.parent
|
|
419
|
-
x.parent
|
|
420
|
-
s.left.color = RBTNColor.BLACK;
|
|
421
|
-
this._rightRotate(x.parent);
|
|
409
|
+
if (s) s.color = x.parent!.color;
|
|
410
|
+
x.parent!.color = RBTNColor.BLACK;
|
|
411
|
+
if (s && s.left) s.left.color = RBTNColor.BLACK;
|
|
412
|
+
this._rightRotate(x.parent!);
|
|
422
413
|
x = this.root;
|
|
423
414
|
}
|
|
424
415
|
}
|
|
@@ -431,9 +422,9 @@ export class RedBlackTree {
|
|
|
431
422
|
* @param {RBTreeNode} u - The parameter "u" represents a RBTreeNode object.
|
|
432
423
|
* @param {RBTreeNode} v - The parameter "v" is a RBTreeNode object.
|
|
433
424
|
*/
|
|
434
|
-
protected _rbTransplant(u:
|
|
435
|
-
if (u.parent ===
|
|
436
|
-
this.
|
|
425
|
+
protected _rbTransplant(u: N, v: N): void {
|
|
426
|
+
if (u.parent === undefined) {
|
|
427
|
+
this._setRoot(v);
|
|
437
428
|
} else if (u === u.parent.left) {
|
|
438
429
|
u.parent.left = v;
|
|
439
430
|
} else {
|
|
@@ -447,12 +438,12 @@ export class RedBlackTree {
|
|
|
447
438
|
* @param {RBTreeNode} k - The parameter `k` is a RBTreeNode object, which represents a node in a
|
|
448
439
|
* red-black tree.
|
|
449
440
|
*/
|
|
450
|
-
protected _fixInsert(k:
|
|
451
|
-
let u:
|
|
452
|
-
while (k.parent.color === 1) {
|
|
453
|
-
if (k.parent === k.parent.parent.right) {
|
|
441
|
+
protected _fixInsert(k: N): void {
|
|
442
|
+
let u: N | undefined;
|
|
443
|
+
while (k.parent && k.parent.color === 1) {
|
|
444
|
+
if (k.parent.parent && k.parent === k.parent.parent.right) {
|
|
454
445
|
u = k.parent.parent.left;
|
|
455
|
-
if (u.color === 1) {
|
|
446
|
+
if (u && u.color === 1) {
|
|
456
447
|
u.color = RBTNColor.BLACK;
|
|
457
448
|
k.parent.color = RBTNColor.BLACK;
|
|
458
449
|
k.parent.parent.color = RBTNColor.RED;
|
|
@@ -463,27 +454,27 @@ export class RedBlackTree {
|
|
|
463
454
|
this._rightRotate(k);
|
|
464
455
|
}
|
|
465
456
|
|
|
466
|
-
k.parent
|
|
467
|
-
k.parent
|
|
468
|
-
this._leftRotate(k.parent
|
|
457
|
+
k.parent!.color = RBTNColor.BLACK;
|
|
458
|
+
k.parent!.parent!.color = RBTNColor.RED;
|
|
459
|
+
this._leftRotate(k.parent!.parent!);
|
|
469
460
|
}
|
|
470
461
|
} else {
|
|
471
|
-
u = k.parent.parent
|
|
462
|
+
u = k.parent.parent!.right;
|
|
472
463
|
|
|
473
|
-
if (u.color === 1) {
|
|
464
|
+
if (u && u.color === 1) {
|
|
474
465
|
u.color = RBTNColor.BLACK;
|
|
475
466
|
k.parent.color = RBTNColor.BLACK;
|
|
476
|
-
k.parent.parent
|
|
477
|
-
k = k.parent.parent
|
|
467
|
+
k.parent.parent!.color = RBTNColor.RED;
|
|
468
|
+
k = k.parent.parent!;
|
|
478
469
|
} else {
|
|
479
470
|
if (k === k.parent.right) {
|
|
480
471
|
k = k.parent;
|
|
481
472
|
this._leftRotate(k);
|
|
482
473
|
}
|
|
483
474
|
|
|
484
|
-
k.parent
|
|
485
|
-
k.parent
|
|
486
|
-
this._rightRotate(k.parent
|
|
475
|
+
k.parent!.color = RBTNColor.BLACK;
|
|
476
|
+
k.parent!.parent!.color = RBTNColor.RED;
|
|
477
|
+
this._rightRotate(k.parent!.parent!);
|
|
487
478
|
}
|
|
488
479
|
}
|
|
489
480
|
if (k === this.root) {
|