min-heap-typed 1.40.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/dist/data-structures/binary-tree/binary-tree.d.ts +14 -3
- package/dist/data-structures/binary-tree/binary-tree.js +52 -10
- package/dist/data-structures/binary-tree/bst.d.ts +2 -2
- package/dist/data-structures/binary-tree/bst.js +3 -3
- package/dist/data-structures/binary-tree/rb-tree.d.ts +96 -9
- package/dist/data-structures/binary-tree/rb-tree.js +377 -12
- package/dist/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +3 -7
- package/dist/types/data-structures/binary-tree/rb-tree.js +11 -6
- package/package.json +2 -2
- 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 +87 -17
- package/src/data-structures/binary-tree/bst.ts +10 -7
- package/src/data-structures/binary-tree/rb-tree.ts +396 -349
- 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/binary-tree/rb-tree.ts +6 -6
- 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
|
@@ -1,358 +1,405 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {IBinaryTree} from '../../interfaces';
|
|
3
|
-
import {BST, BSTNode} from './bst';
|
|
4
|
-
|
|
5
|
-
export class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V>> extends BSTNode<V, N> {
|
|
6
|
-
constructor(key: BTNKey, value?: V) {
|
|
7
|
-
super(key, value);
|
|
8
|
-
this.color = RBColor.RED;
|
|
9
|
-
}
|
|
1
|
+
import {RBTNColor} from '../../types';
|
|
10
2
|
|
|
11
|
-
|
|
3
|
+
export class RBTreeNode {
|
|
4
|
+
key: number;
|
|
5
|
+
parent: RBTreeNode;
|
|
6
|
+
left: RBTreeNode;
|
|
7
|
+
right: RBTreeNode;
|
|
8
|
+
color: number = RBTNColor.BLACK;
|
|
12
9
|
|
|
10
|
+
constructor(key: number, color: RBTNColor = RBTNColor.BLACK) {
|
|
11
|
+
this.key = key;
|
|
12
|
+
this.color = color;
|
|
13
|
+
this.parent = null as unknown as RBTreeNode;
|
|
14
|
+
this.left = null as unknown as RBTreeNode;
|
|
15
|
+
this.right = null as unknown as RBTreeNode;
|
|
16
|
+
}
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(
|
|
19
|
-
|
|
19
|
+
export const SN = new RBTreeNode(0);
|
|
20
|
+
|
|
21
|
+
export class RedBlackTree {
|
|
22
|
+
constructor() {
|
|
23
|
+
this._root = SN;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
protected _root: RBTreeNode;
|
|
27
|
+
|
|
28
|
+
get root(): RBTreeNode {
|
|
29
|
+
return this._root;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
34
|
+
* violations of the red-black tree properties.
|
|
35
|
+
* @param {number} key - The key parameter is a number that represents the value to be inserted into
|
|
36
|
+
* the RBTree.
|
|
37
|
+
* @returns The function does not explicitly return anything.
|
|
38
|
+
*/
|
|
39
|
+
insert(key: number): void {
|
|
40
|
+
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
41
|
+
node.left = SN;
|
|
42
|
+
node.right = SN;
|
|
43
|
+
|
|
44
|
+
let y: RBTreeNode = null as unknown as RBTreeNode;
|
|
45
|
+
let x: RBTreeNode = this.root;
|
|
46
|
+
|
|
47
|
+
while (x !== SN) {
|
|
48
|
+
y = x;
|
|
49
|
+
if (node.key < x.key) {
|
|
50
|
+
x = x.left;
|
|
51
|
+
} else {
|
|
52
|
+
x = x.right;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
node.parent = y;
|
|
57
|
+
if (y === null) {
|
|
58
|
+
this._root = node;
|
|
59
|
+
} else if (node.key < y.key) {
|
|
60
|
+
y.left = node;
|
|
61
|
+
} else {
|
|
62
|
+
y.right = node;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (node.parent === null) {
|
|
66
|
+
node.color = RBTNColor.BLACK;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (node.parent.parent === null) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this._fixInsert(node);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The `delete` function in TypeScript is used to remove a node with a specific key from a red-black
|
|
79
|
+
* tree.
|
|
80
|
+
* @param {RBTreeNode} node - The `node` parameter is of type `RBTreeNode` and represents the current
|
|
81
|
+
* node being processed in the delete operation.
|
|
82
|
+
* @returns The `delete` function does not return anything. It has a return type of `void`.
|
|
83
|
+
*/
|
|
84
|
+
delete(key: number): void {
|
|
85
|
+
const helper = (node: RBTreeNode): void => {
|
|
86
|
+
let z: RBTreeNode = SN;
|
|
87
|
+
let x: RBTreeNode, y: RBTreeNode;
|
|
88
|
+
while (node !== SN) {
|
|
89
|
+
if (node.key === key) {
|
|
90
|
+
z = node;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (node.key <= key) {
|
|
94
|
+
node = node.right;
|
|
95
|
+
} else {
|
|
96
|
+
node = node.left;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (z === SN) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
y = z;
|
|
105
|
+
let yOriginalColor: number = y.color;
|
|
106
|
+
if (z.left === SN) {
|
|
107
|
+
x = z.right;
|
|
108
|
+
this._rbTransplant(z, z.right);
|
|
109
|
+
} else if (z.right === SN) {
|
|
110
|
+
x = z.left;
|
|
111
|
+
this._rbTransplant(z, z.left);
|
|
112
|
+
} else {
|
|
113
|
+
y = this.getLeftMost(z.right);
|
|
114
|
+
yOriginalColor = y.color;
|
|
115
|
+
x = y.right;
|
|
116
|
+
if (y.parent === z) {
|
|
117
|
+
x.parent = y;
|
|
118
|
+
} else {
|
|
119
|
+
this._rbTransplant(y, y.right);
|
|
120
|
+
y.right = z.right;
|
|
121
|
+
y.right.parent = y;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this._rbTransplant(z, y);
|
|
125
|
+
y.left = z.left;
|
|
126
|
+
y.left.parent = y;
|
|
127
|
+
y.color = z.color;
|
|
128
|
+
}
|
|
129
|
+
if (yOriginalColor === RBTNColor.BLACK) {
|
|
130
|
+
this._fixDelete(x);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
helper(this.root);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
isRealNode(node: RBTreeNode): node is RBTreeNode {
|
|
137
|
+
return node !== SN && node !== null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The function `getNode` is a recursive depth-first search algorithm that searches for a node with a
|
|
142
|
+
* given key in a red-black tree.
|
|
143
|
+
* @param {number} key - The key parameter is a number that represents the value we are searching for
|
|
144
|
+
* in the RBTree.
|
|
145
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter that represents the starting
|
|
146
|
+
* point for the search in the binary search tree. If no value is provided for `beginRoot`, it
|
|
147
|
+
* defaults to the root of the binary search tree (`this.root`).
|
|
148
|
+
* @returns a RBTreeNode.
|
|
149
|
+
*/
|
|
150
|
+
getNode(key: number, beginRoot = this.root): RBTreeNode {
|
|
151
|
+
const dfs = (node: RBTreeNode): RBTreeNode => {
|
|
152
|
+
if (this.isRealNode(node)) {
|
|
153
|
+
if (key === node.key) {
|
|
154
|
+
return node;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (key < node.key) return dfs(node.left);
|
|
158
|
+
return dfs(node.right);
|
|
159
|
+
} else {
|
|
160
|
+
return null as unknown as RBTreeNode;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
return dfs(beginRoot);
|
|
20
164
|
}
|
|
21
165
|
|
|
22
|
-
|
|
23
|
-
|
|
166
|
+
/**
|
|
167
|
+
* The function returns the leftmost node in a red-black tree.
|
|
168
|
+
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode, which represents a node in
|
|
169
|
+
* a Red-Black Tree.
|
|
170
|
+
* @returns The leftmost node in the given RBTreeNode.
|
|
171
|
+
*/
|
|
172
|
+
getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
|
|
173
|
+
while (node.left !== null && node.left !== SN) {
|
|
174
|
+
node = node.left;
|
|
175
|
+
}
|
|
176
|
+
return node;
|
|
24
177
|
}
|
|
25
178
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// sibling.left!.color = RBColor.BLACK;
|
|
253
|
-
// sibling.color = RBColor.RED;
|
|
254
|
-
// this._rotateRight(sibling);
|
|
255
|
-
// sibling = node.parent!.right;
|
|
256
|
-
// }
|
|
257
|
-
//
|
|
258
|
-
// // Case 4: The sibling node is black, and the right child is red
|
|
259
|
-
// if (sibling) {
|
|
260
|
-
// sibling.color = node.parent!.color;
|
|
261
|
-
// }
|
|
262
|
-
// if (node.parent) {
|
|
263
|
-
// node.parent.color = RBColor.BLACK;
|
|
264
|
-
// }
|
|
265
|
-
// if (sibling!.right) {
|
|
266
|
-
// sibling!.right.color = RBColor.BLACK;
|
|
267
|
-
// }
|
|
268
|
-
// this._rotateLeft(node.parent!);
|
|
269
|
-
// node = this.root;
|
|
270
|
-
// }
|
|
271
|
-
// } else {
|
|
272
|
-
// // Symmetric case: The parent is the right child of the grandparent
|
|
273
|
-
// sibling = node.parent!.left;
|
|
274
|
-
//
|
|
275
|
-
// if (sibling && this._isNodeRed(sibling)) {
|
|
276
|
-
// // Case 1: The sibling node is red
|
|
277
|
-
// sibling.color = RBColor.BLACK;
|
|
278
|
-
// node.parent!.color = RBColor.RED;
|
|
279
|
-
// this._rotateRight(node.parent!);
|
|
280
|
-
// sibling = node.parent!.left;
|
|
281
|
-
// }
|
|
282
|
-
//
|
|
283
|
-
// if (!sibling) return;
|
|
284
|
-
//
|
|
285
|
-
// if (
|
|
286
|
-
// (!sibling.left || sibling.left.color === RBColor.BLACK) &&
|
|
287
|
-
// (!sibling.right || sibling.right.color === RBColor.BLACK)
|
|
288
|
-
// ) {
|
|
289
|
-
// // Case 2: The sibling node and its children are all black
|
|
290
|
-
// sibling.color = RBColor.RED;
|
|
291
|
-
// node = node.parent!;
|
|
292
|
-
// } else {
|
|
293
|
-
// if (!(sibling.left && this._isNodeRed(sibling.left))) {
|
|
294
|
-
// // Case 3: The sibling node is black, and the right child is red, the left child is black
|
|
295
|
-
// sibling.right!.color = RBColor.BLACK;
|
|
296
|
-
// sibling.color = RBColor.RED;
|
|
297
|
-
// this._rotateLeft(sibling);
|
|
298
|
-
// sibling = node.parent!.left;
|
|
299
|
-
// }
|
|
300
|
-
//
|
|
301
|
-
// // Case 4: The sibling node is black, and the left child is red
|
|
302
|
-
// if (sibling) {
|
|
303
|
-
// sibling.color = node.parent!.color;
|
|
304
|
-
// }
|
|
305
|
-
// if (node.parent) {
|
|
306
|
-
// node.parent.color = RBColor.BLACK;
|
|
307
|
-
// }
|
|
308
|
-
// if (sibling!.left) {
|
|
309
|
-
// sibling!.left.color = RBColor.BLACK;
|
|
310
|
-
// }
|
|
311
|
-
// this._rotateRight(node.parent!);
|
|
312
|
-
// node = this.root;
|
|
313
|
-
// }
|
|
314
|
-
// }
|
|
315
|
-
// }
|
|
316
|
-
//
|
|
317
|
-
// if (node) {
|
|
318
|
-
// node.color = RBColor.BLACK;
|
|
319
|
-
// }
|
|
320
|
-
// }
|
|
321
|
-
//
|
|
322
|
-
// protected _findMin(node: N): N {
|
|
323
|
-
// while (node.left) {
|
|
324
|
-
// node = node.left;
|
|
325
|
-
// }
|
|
326
|
-
// return node;
|
|
327
|
-
// }
|
|
328
|
-
//
|
|
329
|
-
// // Get the replacement node
|
|
330
|
-
// protected _getReplacementNode(node: N): N | null | undefined {
|
|
331
|
-
// if (node.left && node.right) {
|
|
332
|
-
// return this._findSuccessor(node);
|
|
333
|
-
// }
|
|
334
|
-
//
|
|
335
|
-
// if (!node.left && !node.right) {
|
|
336
|
-
// return null; // Return a fake node with color black
|
|
337
|
-
// }
|
|
338
|
-
//
|
|
339
|
-
// return node.left || node.right;
|
|
340
|
-
// }
|
|
341
|
-
//
|
|
342
|
-
// // Find the successor node
|
|
343
|
-
// protected _findSuccessor(node: N): N | null | undefined {
|
|
344
|
-
// if (node.right) {
|
|
345
|
-
// // If the node has a right child, find the minimum node in the right subtree as the successor
|
|
346
|
-
// return this._findMin(node.right);
|
|
347
|
-
// }
|
|
348
|
-
//
|
|
349
|
-
// // Otherwise, traverse upward until finding the first parent whose left child is the current node
|
|
350
|
-
// let parent = node.parent;
|
|
351
|
-
// while (parent && node === parent.right) {
|
|
352
|
-
// node = parent;
|
|
353
|
-
// parent = parent.parent;
|
|
354
|
-
// }
|
|
355
|
-
//
|
|
356
|
-
// return parent;
|
|
357
|
-
// }
|
|
179
|
+
/**
|
|
180
|
+
* The function returns the rightmost node in a red-black tree.
|
|
181
|
+
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
|
|
182
|
+
* @returns the rightmost node in a red-black tree.
|
|
183
|
+
*/
|
|
184
|
+
getRightMost(node: RBTreeNode): RBTreeNode {
|
|
185
|
+
while (node.right !== null && node.right !== SN) {
|
|
186
|
+
node = node.right;
|
|
187
|
+
}
|
|
188
|
+
return node;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The function returns the successor of a given node in a red-black tree.
|
|
193
|
+
* @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.
|
|
194
|
+
* @returns the successor of the given RBTreeNode.
|
|
195
|
+
*/
|
|
196
|
+
getSuccessor(x: RBTreeNode): RBTreeNode {
|
|
197
|
+
if (x.right !== SN) {
|
|
198
|
+
return this.getLeftMost(x.right);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let y: RBTreeNode = x.parent;
|
|
202
|
+
while (y !== SN && y !== null && x === y.right) {
|
|
203
|
+
x = y;
|
|
204
|
+
y = y.parent;
|
|
205
|
+
}
|
|
206
|
+
return y;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The function returns the predecessor of a given node in a red-black tree.
|
|
211
|
+
* @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a
|
|
212
|
+
* Red-Black Tree.
|
|
213
|
+
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
214
|
+
*/
|
|
215
|
+
getPredecessor(x: RBTreeNode): RBTreeNode {
|
|
216
|
+
if (x.left !== SN) {
|
|
217
|
+
return this.getRightMost(x.left);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let y: RBTreeNode = x.parent;
|
|
221
|
+
while (y !== SN && x === y.left) {
|
|
222
|
+
x = y;
|
|
223
|
+
y = y.parent;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return y;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The function performs a left rotation on a red-black tree node.
|
|
231
|
+
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
|
232
|
+
*/
|
|
233
|
+
protected _leftRotate(x: RBTreeNode): void {
|
|
234
|
+
const y: RBTreeNode = x.right;
|
|
235
|
+
x.right = y.left;
|
|
236
|
+
if (y.left !== SN) {
|
|
237
|
+
y.left.parent = x;
|
|
238
|
+
}
|
|
239
|
+
y.parent = x.parent;
|
|
240
|
+
if (x.parent === null) {
|
|
241
|
+
this._root = y;
|
|
242
|
+
} else if (x === x.parent.left) {
|
|
243
|
+
x.parent.left = y;
|
|
244
|
+
} else {
|
|
245
|
+
x.parent.right = y;
|
|
246
|
+
}
|
|
247
|
+
y.left = x;
|
|
248
|
+
x.parent = y;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The function performs a right rotation on a red-black tree node.
|
|
253
|
+
* @param {RBTreeNode} x - x is a RBTreeNode, which represents the node that needs to be right
|
|
254
|
+
* rotated.
|
|
255
|
+
*/
|
|
256
|
+
protected _rightRotate(x: RBTreeNode): void {
|
|
257
|
+
const y: RBTreeNode = x.left;
|
|
258
|
+
x.left = y.right;
|
|
259
|
+
if (y.right !== SN) {
|
|
260
|
+
y.right.parent = x;
|
|
261
|
+
}
|
|
262
|
+
y.parent = x.parent;
|
|
263
|
+
if (x.parent === null) {
|
|
264
|
+
this._root = y;
|
|
265
|
+
} else if (x === x.parent.right) {
|
|
266
|
+
x.parent.right = y;
|
|
267
|
+
} else {
|
|
268
|
+
x.parent.left = y;
|
|
269
|
+
}
|
|
270
|
+
y.right = x;
|
|
271
|
+
x.parent = y;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* The _fixDelete function is used to rebalance the Red-Black Tree after a node deletion.
|
|
276
|
+
* @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a
|
|
277
|
+
* red-black tree.
|
|
278
|
+
*/
|
|
279
|
+
protected _fixDelete(x: RBTreeNode): void {
|
|
280
|
+
let s: RBTreeNode;
|
|
281
|
+
while (x !== this.root && x.color === RBTNColor.BLACK) {
|
|
282
|
+
if (x === x.parent.left) {
|
|
283
|
+
s = x.parent.right;
|
|
284
|
+
if (s.color === 1) {
|
|
285
|
+
s.color = RBTNColor.BLACK;
|
|
286
|
+
x.parent.color = RBTNColor.RED;
|
|
287
|
+
this._leftRotate(x.parent);
|
|
288
|
+
s = x.parent.right;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
292
|
+
s.color = RBTNColor.RED;
|
|
293
|
+
x = x.parent;
|
|
294
|
+
} else {
|
|
295
|
+
if (s.right.color === RBTNColor.BLACK) {
|
|
296
|
+
s.left.color = RBTNColor.BLACK;
|
|
297
|
+
s.color = RBTNColor.RED;
|
|
298
|
+
this._rightRotate(s);
|
|
299
|
+
s = x.parent.right;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
s.color = x.parent.color;
|
|
303
|
+
x.parent.color = RBTNColor.BLACK;
|
|
304
|
+
s.right.color = RBTNColor.BLACK;
|
|
305
|
+
this._leftRotate(x.parent);
|
|
306
|
+
x = this.root;
|
|
307
|
+
}
|
|
308
|
+
} else {
|
|
309
|
+
s = x.parent.left;
|
|
310
|
+
if (s.color === 1) {
|
|
311
|
+
s.color = RBTNColor.BLACK;
|
|
312
|
+
x.parent.color = RBTNColor.RED;
|
|
313
|
+
this._rightRotate(x.parent);
|
|
314
|
+
s = x.parent.left;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
318
|
+
s.color = RBTNColor.RED;
|
|
319
|
+
x = x.parent;
|
|
320
|
+
} else {
|
|
321
|
+
if (s.left.color === RBTNColor.BLACK) {
|
|
322
|
+
s.right.color = RBTNColor.BLACK;
|
|
323
|
+
s.color = RBTNColor.RED;
|
|
324
|
+
this._leftRotate(s);
|
|
325
|
+
s = x.parent.left;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
s.color = x.parent.color;
|
|
329
|
+
x.parent.color = RBTNColor.BLACK;
|
|
330
|
+
s.left.color = RBTNColor.BLACK;
|
|
331
|
+
this._rightRotate(x.parent);
|
|
332
|
+
x = this.root;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
x.color = RBTNColor.BLACK;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* The function `_rbTransplant` replaces one node in a red-black tree with another node.
|
|
341
|
+
* @param {RBTreeNode} u - The parameter "u" represents a RBTreeNode object.
|
|
342
|
+
* @param {RBTreeNode} v - The parameter "v" is a RBTreeNode object.
|
|
343
|
+
*/
|
|
344
|
+
protected _rbTransplant(u: RBTreeNode, v: RBTreeNode): void {
|
|
345
|
+
if (u.parent === null) {
|
|
346
|
+
this._root = v;
|
|
347
|
+
} else if (u === u.parent.left) {
|
|
348
|
+
u.parent.left = v;
|
|
349
|
+
} else {
|
|
350
|
+
u.parent.right = v;
|
|
351
|
+
}
|
|
352
|
+
v.parent = u.parent;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* The `_fixInsert` function is used to fix the red-black tree after an insertion operation.
|
|
357
|
+
* @param {RBTreeNode} k - The parameter `k` is a RBTreeNode object, which represents a node in a
|
|
358
|
+
* red-black tree.
|
|
359
|
+
*/
|
|
360
|
+
protected _fixInsert(k: RBTreeNode): void {
|
|
361
|
+
let u: RBTreeNode;
|
|
362
|
+
while (k.parent.color === 1) {
|
|
363
|
+
if (k.parent === k.parent.parent.right) {
|
|
364
|
+
u = k.parent.parent.left;
|
|
365
|
+
if (u.color === 1) {
|
|
366
|
+
u.color = RBTNColor.BLACK;
|
|
367
|
+
k.parent.color = RBTNColor.BLACK;
|
|
368
|
+
k.parent.parent.color = RBTNColor.RED;
|
|
369
|
+
k = k.parent.parent;
|
|
370
|
+
} else {
|
|
371
|
+
if (k === k.parent.left) {
|
|
372
|
+
k = k.parent;
|
|
373
|
+
this._rightRotate(k);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
k.parent.color = RBTNColor.BLACK;
|
|
377
|
+
k.parent.parent.color = RBTNColor.RED;
|
|
378
|
+
this._leftRotate(k.parent.parent);
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
u = k.parent.parent.right;
|
|
382
|
+
|
|
383
|
+
if (u.color === 1) {
|
|
384
|
+
u.color = RBTNColor.BLACK;
|
|
385
|
+
k.parent.color = RBTNColor.BLACK;
|
|
386
|
+
k.parent.parent.color = RBTNColor.RED;
|
|
387
|
+
k = k.parent.parent;
|
|
388
|
+
} else {
|
|
389
|
+
if (k === k.parent.right) {
|
|
390
|
+
k = k.parent;
|
|
391
|
+
this._leftRotate(k);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
k.parent.color = RBTNColor.BLACK;
|
|
395
|
+
k.parent.parent.color = RBTNColor.RED;
|
|
396
|
+
this._rightRotate(k.parent.parent);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (k === this.root) {
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
this.root.color = RBTNColor.BLACK;
|
|
404
|
+
}
|
|
358
405
|
}
|