min-heap-typed 1.50.5 → 1.50.7
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-multi-map.d.ts +1 -0
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +3 -0
- package/dist/data-structures/binary-tree/binary-tree.js +32 -28
- package/dist/data-structures/binary-tree/bst.js +17 -17
- package/dist/data-structures/binary-tree/rb-tree.d.ts +158 -141
- package/dist/data-structures/binary-tree/rb-tree.js +416 -396
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +1 -0
- package/dist/data-structures/binary-tree/tree-multi-map.js +84 -76
- package/dist/types/common.d.ts +6 -0
- package/dist/types/common.js +8 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +5 -1
- package/src/data-structures/binary-tree/avl-tree.ts +1 -1
- package/src/data-structures/binary-tree/binary-tree.ts +31 -29
- package/src/data-structures/binary-tree/bst.ts +18 -18
- package/src/data-structures/binary-tree/rb-tree.ts +436 -405
- package/src/data-structures/binary-tree/tree-multi-map.ts +85 -82
- package/src/types/common.ts +7 -0
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
* data-structure-typed
|
|
3
|
-
*
|
|
4
|
-
* @author Tyler Zeng
|
|
5
|
-
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
|
-
* @license MIT License
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
1
|
+
import type {
|
|
10
2
|
BinaryTreeDeleteResult,
|
|
11
3
|
BSTNKeyOrNode,
|
|
12
4
|
BTNCallback,
|
|
13
5
|
KeyOrNodeOrEntry,
|
|
14
|
-
RBTNColor,
|
|
15
6
|
RBTreeOptions,
|
|
16
7
|
RedBlackTreeNested,
|
|
17
8
|
RedBlackTreeNodeNested
|
|
18
9
|
} from '../../types';
|
|
10
|
+
import { CRUD, RBTNColor } from '../../types';
|
|
19
11
|
import { BST, BSTNode } from './bst';
|
|
20
12
|
import { IBinaryTree } from '../../interfaces';
|
|
21
13
|
|
|
@@ -44,7 +36,7 @@ export class RedBlackTreeNode<
|
|
|
44
36
|
|
|
45
37
|
/**
|
|
46
38
|
* The function returns the color value of a variable.
|
|
47
|
-
* @returns The color value stored in the
|
|
39
|
+
* @returns The color value stored in the private variable `_color`.
|
|
48
40
|
*/
|
|
49
41
|
get color(): RBTNColor {
|
|
50
42
|
return this._color;
|
|
@@ -59,13 +51,6 @@ export class RedBlackTreeNode<
|
|
|
59
51
|
}
|
|
60
52
|
}
|
|
61
53
|
|
|
62
|
-
/**
|
|
63
|
-
* 1. Each node is either red or black.
|
|
64
|
-
* 2. The root node is always black.
|
|
65
|
-
* 3. Leaf nodes are typically Sentinel nodes and are considered black.
|
|
66
|
-
* 4. Red nodes must have black children.
|
|
67
|
-
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
68
|
-
*/
|
|
69
54
|
export class RedBlackTree<
|
|
70
55
|
K = any,
|
|
71
56
|
V = any,
|
|
@@ -75,62 +60,54 @@ export class RedBlackTree<
|
|
|
75
60
|
extends BST<K, V, NODE, TREE>
|
|
76
61
|
implements IBinaryTree<K, V, NODE, TREE> {
|
|
77
62
|
/**
|
|
78
|
-
* This is the constructor function for a Red-Black Tree data structure in TypeScript
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* only a subset of the properties defined in the `RBTreeOptions` interface.
|
|
63
|
+
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
|
|
64
|
+
* @param keysOrNodesOrEntries - The `keysOrNodesOrEntries` parameter is an iterable object that can
|
|
65
|
+
* contain keys, nodes, or entries. It is used to initialize the RBTree with the provided keys,
|
|
66
|
+
* nodes, or entries.
|
|
67
|
+
* @param [options] - The `options` parameter is an optional object that can be passed to the
|
|
68
|
+
* constructor. It allows you to customize the behavior of the RBTree. It can include properties such
|
|
69
|
+
* as `compareKeys`, `compareValues`, `allowDuplicates`, etc. These properties define how the RBTree
|
|
70
|
+
* should compare keys and
|
|
87
71
|
*/
|
|
88
72
|
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: RBTreeOptions<K>) {
|
|
89
73
|
super([], options);
|
|
90
74
|
|
|
91
|
-
this._root = this.
|
|
92
|
-
if (keysOrNodesOrEntries) super.addMany(keysOrNodesOrEntries);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
protected _Sentinel: NODE = new RedBlackTreeNode<K, V>(NaN as K) as unknown as NODE;
|
|
75
|
+
this._root = this.SENTINEL;
|
|
96
76
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
*/
|
|
101
|
-
get Sentinel(): NODE {
|
|
102
|
-
return this._Sentinel;
|
|
77
|
+
if (keysOrNodesOrEntries) {
|
|
78
|
+
this.addMany(keysOrNodesOrEntries);
|
|
79
|
+
}
|
|
103
80
|
}
|
|
104
81
|
|
|
105
|
-
protected
|
|
82
|
+
protected _SENTINEL: NODE = new RedBlackTreeNode<K, V>(NaN as K) as unknown as NODE;
|
|
106
83
|
|
|
107
84
|
/**
|
|
108
|
-
* The function returns the
|
|
109
|
-
* @returns The
|
|
85
|
+
* The function returns the value of the _SENTINEL property.
|
|
86
|
+
* @returns The method is returning the value of the `_SENTINEL` property.
|
|
110
87
|
*/
|
|
111
|
-
get
|
|
112
|
-
return this.
|
|
88
|
+
get SENTINEL(): NODE {
|
|
89
|
+
return this._SENTINEL;
|
|
113
90
|
}
|
|
114
91
|
|
|
115
|
-
protected
|
|
92
|
+
protected override _root: NODE | undefined;
|
|
116
93
|
|
|
117
94
|
/**
|
|
118
|
-
* The function returns the
|
|
119
|
-
* @returns The
|
|
95
|
+
* The function returns the root node of a tree or undefined if there is no root.
|
|
96
|
+
* @returns The root node of the tree structure, or undefined if there is no root node.
|
|
120
97
|
*/
|
|
121
|
-
get
|
|
122
|
-
return this.
|
|
98
|
+
override get root(): NODE | undefined {
|
|
99
|
+
return this._root;
|
|
123
100
|
}
|
|
124
101
|
|
|
125
102
|
/**
|
|
126
103
|
* The function creates a new Red-Black Tree node with the specified key, value, and color.
|
|
127
|
-
* @param {K} key - The key parameter
|
|
128
|
-
*
|
|
104
|
+
* @param {K} key - The key parameter represents the key of the node being created. It is of type K,
|
|
105
|
+
* which is a generic type representing the key's data type.
|
|
129
106
|
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
|
|
130
|
-
* associated with the node. It is
|
|
131
|
-
* specific type when using the `createNode` method.
|
|
107
|
+
* associated with the key in the node. It is not required and can be omitted if not needed.
|
|
132
108
|
* @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
|
|
133
|
-
* Red-Black Tree. It
|
|
109
|
+
* Red-Black Tree. It is an optional parameter with a default value of "RBTNColor.BLACK". The color
|
|
110
|
+
* can be either "RBTNColor.RED" or "RBTNColor.BLACK".
|
|
134
111
|
* @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
|
|
135
112
|
* value, and color.
|
|
136
113
|
*/
|
|
@@ -139,10 +116,10 @@ export class RedBlackTree<
|
|
|
139
116
|
}
|
|
140
117
|
|
|
141
118
|
/**
|
|
142
|
-
* The function creates a Red-Black Tree with the
|
|
143
|
-
* @param
|
|
144
|
-
*
|
|
145
|
-
*
|
|
119
|
+
* The function creates a Red-Black Tree with the given options and returns it.
|
|
120
|
+
* @param [options] - The `options` parameter is an optional object that contains configuration
|
|
121
|
+
* options for creating the Red-Black Tree. It is of type `RBTreeOptions<K>`, where `K` represents
|
|
122
|
+
* the type of keys in the tree.
|
|
146
123
|
* @returns a new instance of a RedBlackTree object.
|
|
147
124
|
*/
|
|
148
125
|
override createTree(options?: RBTreeOptions<K>): TREE {
|
|
@@ -153,12 +130,19 @@ export class RedBlackTree<
|
|
|
153
130
|
}
|
|
154
131
|
|
|
155
132
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*
|
|
133
|
+
* Time Complexity: O(1)
|
|
134
|
+
* Space Complexity: O(1)
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Time Complexity: O(1)
|
|
139
|
+
* Space Complexity: O(1)
|
|
140
|
+
*
|
|
141
|
+
* The function `keyValueOrEntryToNode` takes a key, value, or entry and returns a node if it is
|
|
142
|
+
* valid, otherwise it returns undefined.
|
|
143
|
+
* @param {KeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntry - The key, value, or entry to convert.
|
|
144
|
+
* @param {V} [value] - The value associated with the key (if `keyOrNodeOrEntry` is a key).
|
|
145
|
+
* @returns {NODE | undefined} - The corresponding Red-Black Tree node, or `undefined` if conversion fails.
|
|
162
146
|
*/
|
|
163
147
|
override keyValueOrEntryToNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): NODE | undefined {
|
|
164
148
|
let node: NODE | undefined;
|
|
@@ -183,93 +167,128 @@ export class RedBlackTree<
|
|
|
183
167
|
}
|
|
184
168
|
|
|
185
169
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
|
|
170
|
+
* Time Complexity: O(1)
|
|
171
|
+
* Space Complexity: O(1)
|
|
172
|
+
* /
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Time Complexity: O(1)
|
|
176
|
+
* Space Complexity: O(1)
|
|
177
|
+
*
|
|
178
|
+
* The function checks if the input is an instance of the RedBlackTreeNode class.
|
|
179
|
+
* @param {KeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntry - The object to check.
|
|
180
|
+
* @returns {boolean} - `true` if the object is a Red-Black Tree node, `false` otherwise.
|
|
190
181
|
*/
|
|
191
182
|
override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is NODE {
|
|
192
183
|
return keyOrNodeOrEntry instanceof RedBlackTreeNode;
|
|
193
184
|
}
|
|
194
185
|
|
|
195
186
|
/**
|
|
187
|
+
* Time Complexity: O(1)
|
|
188
|
+
* Space Complexity: O(1)
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Time Complexity: O(1)
|
|
193
|
+
* Space Complexity: O(1)
|
|
194
|
+
*
|
|
196
195
|
* The function checks if a given node is a real node in a Red-Black Tree.
|
|
197
196
|
* @param {NODE | undefined} node - The `node` parameter is of type `NODE | undefined`, which means
|
|
198
197
|
* it can either be of type `NODE` or `undefined`.
|
|
199
198
|
* @returns a boolean value.
|
|
200
199
|
*/
|
|
201
200
|
override isRealNode(node: NODE | undefined): node is NODE {
|
|
202
|
-
if (node === this.
|
|
201
|
+
if (node === this.SENTINEL || node === undefined) return false;
|
|
203
202
|
return node instanceof RedBlackTreeNode;
|
|
204
203
|
}
|
|
205
204
|
|
|
206
205
|
/**
|
|
207
206
|
* Time Complexity: O(log n)
|
|
208
207
|
* Space Complexity: O(1)
|
|
209
|
-
* On average (where n is the number of nodes in the tree)
|
|
210
208
|
*/
|
|
211
209
|
|
|
212
210
|
/**
|
|
213
211
|
* Time Complexity: O(log n)
|
|
214
212
|
* Space Complexity: O(1)
|
|
215
213
|
*
|
|
216
|
-
* The `
|
|
217
|
-
*
|
|
214
|
+
* The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and
|
|
215
|
+
* callback function.
|
|
216
|
+
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value or key
|
|
217
|
+
* that you want to search for in the binary search tree. It can be of any type that is compatible
|
|
218
|
+
* with the type of nodes in the tree.
|
|
219
|
+
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
220
|
+
* the tree. It is used to determine whether a node matches the given identifier. The `callback`
|
|
221
|
+
* function should take a node as its parameter and return a value that can be compared to the
|
|
222
|
+
* `identifier` parameter.
|
|
223
|
+
* @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
|
|
224
|
+
* search tree. It can be either a key or a node. If it is a key, it will be converted to a node
|
|
225
|
+
* using the `ensureNode` method. If it is not provided, the `root`
|
|
226
|
+
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
227
|
+
* be performed when searching for nodes in the binary search tree. It is an optional parameter and
|
|
228
|
+
* its default value is taken from the `iterationType` property of the class.
|
|
229
|
+
* @returns The method is returning a value of type `NODE | null | undefined`.
|
|
230
|
+
*/
|
|
231
|
+
override getNode<C extends BTNCallback<NODE>>(
|
|
232
|
+
identifier: ReturnType<C> | undefined,
|
|
233
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
234
|
+
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
235
|
+
iterationType = this.iterationType
|
|
236
|
+
): NODE | null | undefined {
|
|
237
|
+
if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
|
|
238
|
+
return super.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Time Complexity: O(1)
|
|
243
|
+
* Space Complexity: O(1)
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Time Complexity: O(1)
|
|
248
|
+
* Space Complexity: O(1)
|
|
249
|
+
*
|
|
250
|
+
* The "clear" function sets the root node of a data structure to a sentinel value and resets the
|
|
251
|
+
* size counter to zero.
|
|
252
|
+
*/
|
|
253
|
+
override clear() {
|
|
254
|
+
super.clear();
|
|
255
|
+
this._root = this.SENTINEL;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Time Complexity: O(log n)
|
|
260
|
+
* Space Complexity: O(1)
|
|
261
|
+
*/
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Time Complexity: O(log n)
|
|
265
|
+
* Space Complexity: O(1)
|
|
266
|
+
*
|
|
267
|
+
* The function adds a new node to a Red-Black Tree data structure and returns a boolean indicating
|
|
268
|
+
* whether the operation was successful.
|
|
218
269
|
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be either a key, a node, or an
|
|
219
270
|
* entry.
|
|
220
|
-
* @param {V} [value] - The `value` parameter
|
|
221
|
-
*
|
|
222
|
-
* @returns The method
|
|
271
|
+
* @param {V} [value] - The `value` parameter is the value associated with the key that is being
|
|
272
|
+
* added to the tree.
|
|
273
|
+
* @returns The method is returning a boolean value. It returns true if the node was successfully
|
|
274
|
+
* added or updated, and false otherwise.
|
|
223
275
|
*/
|
|
224
276
|
override add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
|
|
225
277
|
const newNode = this.keyValueOrEntryToNode(keyOrNodeOrEntry, value);
|
|
226
|
-
if (newNode
|
|
227
|
-
|
|
228
|
-
newNode.left = this._Sentinel;
|
|
229
|
-
newNode.right = this._Sentinel;
|
|
278
|
+
if (!this.isRealNode(newNode)) return false;
|
|
230
279
|
|
|
231
|
-
|
|
232
|
-
let x: NODE | undefined = this.root;
|
|
280
|
+
const insertStatus = this._insert(newNode);
|
|
233
281
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
x = x?.right;
|
|
241
|
-
} else {
|
|
242
|
-
if (newNode !== x) {
|
|
243
|
-
this._replaceNode(x, newNode);
|
|
244
|
-
}
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
282
|
+
if (insertStatus === CRUD.CREATED) {
|
|
283
|
+
// Ensure the root is black
|
|
284
|
+
if (this.isRealNode(this._root)) {
|
|
285
|
+
this._root.color = RBTNColor.BLACK;
|
|
286
|
+
} else {
|
|
287
|
+
return false;
|
|
247
288
|
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
newNode.parent = y;
|
|
251
|
-
if (y === undefined) {
|
|
252
|
-
this._setRoot(newNode);
|
|
253
|
-
} else if (newNode.key < y.key) {
|
|
254
|
-
y.left = newNode;
|
|
255
|
-
} else {
|
|
256
|
-
y.right = newNode;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (newNode.parent === undefined) {
|
|
260
|
-
newNode.color = RBTNColor.BLACK;
|
|
261
289
|
this._size++;
|
|
262
|
-
return
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (newNode.parent.parent === undefined) {
|
|
266
|
-
this._size++;
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
this._fixInsert(newNode);
|
|
271
|
-
this._size++;
|
|
272
|
-
return true;
|
|
290
|
+
return true;
|
|
291
|
+
} else return insertStatus === CRUD.UPDATED;
|
|
273
292
|
}
|
|
274
293
|
|
|
275
294
|
/**
|
|
@@ -281,113 +300,88 @@ export class RedBlackTree<
|
|
|
281
300
|
* Time Complexity: O(log n)
|
|
282
301
|
* Space Complexity: O(1)
|
|
283
302
|
*
|
|
284
|
-
* The `delete`
|
|
285
|
-
*
|
|
286
|
-
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
* @param {C} callback - The `callback` parameter is a function that
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
|
|
295
|
-
|
|
303
|
+
* The function `delete` in a binary tree class deletes a node from the tree and fixes the tree if
|
|
304
|
+
* necessary.
|
|
305
|
+
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the
|
|
306
|
+
* identifier of the node that needs to be deleted from the binary tree. It can be of any type that
|
|
307
|
+
* is returned by the callback function `C`. It can also be `null` or `undefined` if the node to be
|
|
308
|
+
* deleted is not found.
|
|
309
|
+
* @param {C} callback - The `callback` parameter is a function that is used to retrieve a node from
|
|
310
|
+
* the binary tree based on its identifier. It is an optional parameter and if not provided, the
|
|
311
|
+
* `_defaultOneParamCallback` function is used as the default callback. The callback function should
|
|
312
|
+
* return the identifier of the node to
|
|
313
|
+
* @returns an array of BinaryTreeDeleteResult<NODE> objects.
|
|
314
|
+
*/
|
|
315
|
+
override delete<C extends BTNCallback<NODE>>(
|
|
296
316
|
identifier: ReturnType<C> | null | undefined,
|
|
297
317
|
callback: C = this._defaultOneParamCallback as C
|
|
298
318
|
): BinaryTreeDeleteResult<NODE>[] {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const helper = (node: NODE | undefined): void => {
|
|
302
|
-
let z: NODE = this._Sentinel;
|
|
303
|
-
let x: NODE | undefined, y: NODE;
|
|
304
|
-
while (node !== this._Sentinel) {
|
|
305
|
-
if (node && callback(node) === identifier) {
|
|
306
|
-
z = node;
|
|
307
|
-
}
|
|
319
|
+
if (identifier === null) return [];
|
|
320
|
+
const results: BinaryTreeDeleteResult<NODE>[] = [];
|
|
308
321
|
|
|
309
|
-
|
|
310
|
-
node = node.right;
|
|
311
|
-
} else {
|
|
312
|
-
node = node?.left;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
322
|
+
const nodeToDelete = this.isRealNode(identifier) ? identifier : this.getNode(identifier, callback);
|
|
315
323
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
324
|
+
if (!nodeToDelete) {
|
|
325
|
+
return results;
|
|
326
|
+
}
|
|
320
327
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
let originalColor = nodeToDelete.color;
|
|
329
|
+
let replacementNode: NODE | undefined;
|
|
330
|
+
|
|
331
|
+
if (!this.isRealNode(nodeToDelete.left)) {
|
|
332
|
+
replacementNode = nodeToDelete.right;
|
|
333
|
+
this._transplant(nodeToDelete, nodeToDelete.right);
|
|
334
|
+
} else if (!this.isRealNode(nodeToDelete.right)) {
|
|
335
|
+
replacementNode = nodeToDelete.left;
|
|
336
|
+
this._transplant(nodeToDelete, nodeToDelete.left);
|
|
337
|
+
} else {
|
|
338
|
+
const successor = this.getLeftMost(nodeToDelete.right);
|
|
339
|
+
if (successor) {
|
|
340
|
+
originalColor = successor.color;
|
|
341
|
+
replacementNode = successor.right;
|
|
342
|
+
|
|
343
|
+
if (successor.parent === nodeToDelete) {
|
|
344
|
+
if (this.isRealNode(replacementNode)) {
|
|
345
|
+
replacementNode.parent = successor;
|
|
346
|
+
}
|
|
335
347
|
} else {
|
|
336
|
-
this.
|
|
337
|
-
|
|
338
|
-
|
|
348
|
+
this._transplant(successor, successor.right);
|
|
349
|
+
successor.right = nodeToDelete.right;
|
|
350
|
+
if (this.isRealNode(successor.right)) {
|
|
351
|
+
successor.right.parent = successor;
|
|
352
|
+
}
|
|
339
353
|
}
|
|
340
354
|
|
|
341
|
-
this.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this._fixDelete(x!);
|
|
355
|
+
this._transplant(nodeToDelete, successor);
|
|
356
|
+
successor.left = nodeToDelete.left;
|
|
357
|
+
if (this.isRealNode(successor.left)) {
|
|
358
|
+
successor.left.parent = successor;
|
|
359
|
+
}
|
|
360
|
+
successor.color = nodeToDelete.color;
|
|
348
361
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
362
|
+
}
|
|
363
|
+
this._size--;
|
|
364
|
+
|
|
365
|
+
// If the original color was black, fix the tree
|
|
366
|
+
if (originalColor === RBTNColor.BLACK) {
|
|
367
|
+
this._deleteFixup(replacementNode);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
results.push({ deleted: nodeToDelete, needBalanced: undefined });
|
|
371
|
+
|
|
372
|
+
return results;
|
|
354
373
|
}
|
|
355
374
|
|
|
356
375
|
/**
|
|
357
|
-
*
|
|
358
|
-
*
|
|
376
|
+
* The function sets the root of a tree-like structure and updates the parent property of the new
|
|
377
|
+
* root.
|
|
378
|
+
* @param {NODE | undefined} v - v is a parameter of type NODE or undefined.
|
|
359
379
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
* The function `getNode` retrieves a single node from a binary tree based on a given identifier and
|
|
366
|
-
* callback function.
|
|
367
|
-
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value used to
|
|
368
|
-
* identify the node you want to retrieve. It can be of any type that is the return type of the `C`
|
|
369
|
-
* callback function. If the `identifier` is `undefined`, it means you want to retrieve the first
|
|
370
|
-
* node that matches the other criteria
|
|
371
|
-
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
372
|
-
* the binary tree. It is used to determine if a node matches the given identifier. The `callback`
|
|
373
|
-
* function should take a single parameter of type `NODE` (the type of the nodes in the binary tree) and
|
|
374
|
-
* @param {K | NODE | undefined} beginRoot - The `beginRoot` parameter is the starting point for
|
|
375
|
-
* searching for a node in a binary tree. It can be either a key value or a node object. If it is not
|
|
376
|
-
* provided, the search will start from the root of the binary tree.
|
|
377
|
-
* @param iterationType - The `iterationType` parameter is a variable that determines the type of
|
|
378
|
-
* iteration to be performed when searching for nodes in the binary tree. It is used in the
|
|
379
|
-
* `getNodes` method, which is called within the `getNode` method.
|
|
380
|
-
* @returns a value of type `NODE`, `null`, or `undefined`.
|
|
381
|
-
*/
|
|
382
|
-
getNode<C extends BTNCallback<NODE>>(
|
|
383
|
-
identifier: ReturnType<C> | undefined,
|
|
384
|
-
callback: C = this._defaultOneParamCallback as C,
|
|
385
|
-
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
386
|
-
iterationType = this.iterationType
|
|
387
|
-
): NODE | null | undefined {
|
|
388
|
-
if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
|
|
389
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
390
|
-
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
380
|
+
protected override _setRoot(v: NODE | undefined) {
|
|
381
|
+
if (v) {
|
|
382
|
+
v.parent = undefined;
|
|
383
|
+
}
|
|
384
|
+
this._root = v;
|
|
391
385
|
}
|
|
392
386
|
|
|
393
387
|
/**
|
|
@@ -399,11 +393,18 @@ export class RedBlackTree<
|
|
|
399
393
|
* Time Complexity: O(1)
|
|
400
394
|
* Space Complexity: O(1)
|
|
401
395
|
*
|
|
402
|
-
* The
|
|
396
|
+
* The function replaces an old node with a new node while preserving the color of the old node.
|
|
397
|
+
* @param {NODE} oldNode - The `oldNode` parameter represents the node that needs to be replaced in
|
|
398
|
+
* the data structure.
|
|
399
|
+
* @param {NODE} newNode - The `newNode` parameter is the new node that will replace the old node in
|
|
400
|
+
* the data structure.
|
|
401
|
+
* @returns The method is returning the result of calling the `_replaceNode` method from the
|
|
402
|
+
* superclass, with the `oldNode` and `newNode` parameters.
|
|
403
403
|
*/
|
|
404
|
-
override
|
|
405
|
-
|
|
406
|
-
|
|
404
|
+
protected override _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
405
|
+
newNode.color = oldNode.color;
|
|
406
|
+
|
|
407
|
+
return super._replaceNode(oldNode, newNode);
|
|
407
408
|
}
|
|
408
409
|
|
|
409
410
|
/**
|
|
@@ -415,36 +416,45 @@ export class RedBlackTree<
|
|
|
415
416
|
* Time Complexity: O(log n)
|
|
416
417
|
* Space Complexity: O(1)
|
|
417
418
|
*
|
|
418
|
-
* The function
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
419
|
+
* The `_insert` function inserts or updates a node in a binary search tree and performs necessary
|
|
420
|
+
* fix-ups to maintain the red-black tree properties.
|
|
421
|
+
* @param {NODE} node - The `node` parameter represents the node that needs to be inserted into a
|
|
422
|
+
* binary search tree. It contains a `key` property that is used to determine the position of the
|
|
423
|
+
* node in the tree.
|
|
424
|
+
* @returns {'inserted' | 'updated'} - The result of the insertion.
|
|
425
|
+
*/
|
|
426
|
+
protected _insert(node: NODE): CRUD {
|
|
427
|
+
let current = this.root;
|
|
428
|
+
let parent: NODE | undefined = undefined;
|
|
429
|
+
|
|
430
|
+
while (this.isRealNode(current)) {
|
|
431
|
+
parent = current;
|
|
432
|
+
if (node.key < current.key) {
|
|
433
|
+
current = current.left ?? this.SENTINEL;
|
|
434
|
+
} else if (node.key > current.key) {
|
|
435
|
+
current = current.right ?? this.SENTINEL;
|
|
436
|
+
} else {
|
|
437
|
+
this._replaceNode(current, node);
|
|
438
|
+
return CRUD.UPDATED;
|
|
439
|
+
}
|
|
426
440
|
}
|
|
427
441
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
442
|
+
node.parent = parent;
|
|
443
|
+
|
|
444
|
+
if (!parent) {
|
|
445
|
+
this._setRoot(node);
|
|
446
|
+
} else if (node.key < parent.key) {
|
|
447
|
+
parent.left = node;
|
|
448
|
+
} else {
|
|
449
|
+
parent.right = node;
|
|
432
450
|
}
|
|
433
451
|
|
|
434
|
-
|
|
435
|
-
|
|
452
|
+
node.left = this.SENTINEL;
|
|
453
|
+
node.right = this.SENTINEL;
|
|
454
|
+
node.color = RBTNColor.RED;
|
|
436
455
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
* root node.
|
|
440
|
-
* @param {NODE} v - The parameter "v" is of type "NODE", which represents a node in a data
|
|
441
|
-
* structure.
|
|
442
|
-
*/
|
|
443
|
-
protected override _setRoot(v: NODE) {
|
|
444
|
-
if (v) {
|
|
445
|
-
v.parent = undefined;
|
|
446
|
-
}
|
|
447
|
-
this._root = v;
|
|
456
|
+
this._insertFixup(node);
|
|
457
|
+
return CRUD.CREATED;
|
|
448
458
|
}
|
|
449
459
|
|
|
450
460
|
/**
|
|
@@ -456,59 +466,22 @@ export class RedBlackTree<
|
|
|
456
466
|
* Time Complexity: O(1)
|
|
457
467
|
* Space Complexity: O(1)
|
|
458
468
|
*
|
|
459
|
-
* The function
|
|
460
|
-
* @param {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (x.right) {
|
|
464
|
-
const y: NODE = x.right;
|
|
465
|
-
x.right = y.left;
|
|
466
|
-
if (y.left !== this._Sentinel) {
|
|
467
|
-
if (y.left) y.left.parent = x;
|
|
468
|
-
}
|
|
469
|
-
y.parent = x.parent;
|
|
470
|
-
if (x.parent === undefined) {
|
|
471
|
-
this._setRoot(y);
|
|
472
|
-
} else if (x === x.parent.left) {
|
|
473
|
-
x.parent.left = y;
|
|
474
|
-
} else {
|
|
475
|
-
x.parent.right = y;
|
|
476
|
-
}
|
|
477
|
-
y.left = x;
|
|
478
|
-
x.parent = y;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Time Complexity: O(1)
|
|
484
|
-
* Space Complexity: O(1)
|
|
469
|
+
* The function `_transplant` is used to replace a node `u` with another node `v` in a binary tree.
|
|
470
|
+
* @param {NODE} u - The parameter "u" represents a node in a binary tree.
|
|
471
|
+
* @param {NODE | undefined} v - The parameter `v` is of type `NODE | undefined`, which means it can
|
|
472
|
+
* either be a `NODE` object or `undefined`.
|
|
485
473
|
*/
|
|
474
|
+
protected _transplant(u: NODE, v: NODE | undefined): void {
|
|
475
|
+
if (!u.parent) {
|
|
476
|
+
this._setRoot(v);
|
|
477
|
+
} else if (u === u.parent.left) {
|
|
478
|
+
u.parent.left = v;
|
|
479
|
+
} else {
|
|
480
|
+
u.parent.right = v;
|
|
481
|
+
}
|
|
486
482
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
* Space Complexity: O(1)
|
|
490
|
-
*
|
|
491
|
-
* The function performs a right rotation on a red-black tree node.
|
|
492
|
-
* @param {RedBlackTreeNode} x - x is a RedBlackTreeNode, which represents the node that needs to be right
|
|
493
|
-
* rotated.
|
|
494
|
-
*/
|
|
495
|
-
protected _rightRotate(x: NODE): void {
|
|
496
|
-
if (x.left) {
|
|
497
|
-
const y: NODE = x.left;
|
|
498
|
-
x.left = y.right;
|
|
499
|
-
if (y.right !== this._Sentinel) {
|
|
500
|
-
if (y.right) y.right.parent = x;
|
|
501
|
-
}
|
|
502
|
-
y.parent = x.parent;
|
|
503
|
-
if (x.parent === undefined) {
|
|
504
|
-
this._setRoot(y);
|
|
505
|
-
} else if (x === x.parent.right) {
|
|
506
|
-
x.parent.right = y;
|
|
507
|
-
} else {
|
|
508
|
-
x.parent.left = y;
|
|
509
|
-
}
|
|
510
|
-
y.right = x;
|
|
511
|
-
x.parent = y;
|
|
483
|
+
if (v) {
|
|
484
|
+
v.parent = u.parent;
|
|
512
485
|
}
|
|
513
486
|
}
|
|
514
487
|
|
|
@@ -521,64 +494,66 @@ export class RedBlackTree<
|
|
|
521
494
|
* Time Complexity: O(log n)
|
|
522
495
|
* Space Complexity: O(1)
|
|
523
496
|
*
|
|
524
|
-
* The `
|
|
525
|
-
* @param {
|
|
526
|
-
*
|
|
527
|
-
*/
|
|
528
|
-
protected
|
|
529
|
-
|
|
530
|
-
while (
|
|
531
|
-
if
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
497
|
+
* The `_insertFixup` function is used to fix the Red-Black Tree after inserting a new node.
|
|
498
|
+
* @param {NODE | undefined} z - The parameter `z` represents a node in the Red-Black Tree. It can
|
|
499
|
+
* either be a valid node object or `undefined`.
|
|
500
|
+
*/
|
|
501
|
+
protected _insertFixup(z: NODE | undefined): void {
|
|
502
|
+
// Continue fixing the tree as long as the parent of z is red
|
|
503
|
+
while (z?.parent?.color === RBTNColor.RED) {
|
|
504
|
+
// Check if the parent of z is the left child of its parent
|
|
505
|
+
if (z.parent === z.parent.parent?.left) {
|
|
506
|
+
// Case 1: The uncle (y) of z is red
|
|
507
|
+
const y = z.parent.parent.right;
|
|
508
|
+
if (y?.color === RBTNColor.RED) {
|
|
509
|
+
// Set colors to restore properties of Red-Black Tree
|
|
510
|
+
z.parent.color = RBTNColor.BLACK;
|
|
511
|
+
y.color = RBTNColor.BLACK;
|
|
512
|
+
z.parent.parent.color = RBTNColor.RED;
|
|
513
|
+
// Move up the tree to continue fixing
|
|
514
|
+
z = z.parent.parent;
|
|
540
515
|
} else {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
516
|
+
// Case 2: The uncle (y) of z is black, and z is a right child
|
|
517
|
+
if (z === z.parent.right) {
|
|
518
|
+
// Perform a left rotation to transform the case into Case 3
|
|
519
|
+
z = z.parent;
|
|
520
|
+
this._leftRotate(z);
|
|
544
521
|
}
|
|
545
522
|
|
|
546
|
-
//
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
523
|
+
// Case 3: The uncle (y) of z is black, and z is a left child
|
|
524
|
+
// Adjust colors and perform a right rotation
|
|
525
|
+
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
526
|
+
z.parent.color = RBTNColor.BLACK;
|
|
527
|
+
z.parent.parent.color = RBTNColor.RED;
|
|
528
|
+
this._rightRotate(z.parent.parent);
|
|
550
529
|
}
|
|
551
|
-
this._leftRotate(k.parent!.parent!);
|
|
552
530
|
}
|
|
553
531
|
} else {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
532
|
+
// Symmetric case for the right child (left and right exchanged)
|
|
533
|
+
// Follow the same logic as above with left and right exchanged
|
|
534
|
+
const y: NODE | undefined = z?.parent?.parent?.left;
|
|
535
|
+
if (y?.color === RBTNColor.RED) {
|
|
536
|
+
z.parent.color = RBTNColor.BLACK;
|
|
537
|
+
y.color = RBTNColor.BLACK;
|
|
538
|
+
z.parent.parent!.color = RBTNColor.RED;
|
|
539
|
+
z = z.parent.parent;
|
|
562
540
|
} else {
|
|
563
|
-
if (
|
|
564
|
-
|
|
565
|
-
this.
|
|
541
|
+
if (z === z.parent.left) {
|
|
542
|
+
z = z.parent;
|
|
543
|
+
this._rightRotate(z);
|
|
566
544
|
}
|
|
567
545
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
546
|
+
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
547
|
+
z.parent.color = RBTNColor.BLACK;
|
|
548
|
+
z.parent.parent.color = RBTNColor.RED;
|
|
549
|
+
this._leftRotate(z.parent.parent);
|
|
572
550
|
}
|
|
573
|
-
this._rightRotate(k.parent!.parent!);
|
|
574
551
|
}
|
|
575
552
|
}
|
|
576
|
-
|
|
577
|
-
if (k === this.root) {
|
|
578
|
-
break;
|
|
579
|
-
}
|
|
580
553
|
}
|
|
581
|
-
|
|
554
|
+
|
|
555
|
+
// Ensure that the root is black after fixing
|
|
556
|
+
if (this.isRealNode(this._root)) this._root.color = RBTNColor.BLACK;
|
|
582
557
|
}
|
|
583
558
|
|
|
584
559
|
/**
|
|
@@ -590,67 +565,82 @@ export class RedBlackTree<
|
|
|
590
565
|
* Time Complexity: O(log n)
|
|
591
566
|
* Space Complexity: O(1)
|
|
592
567
|
*
|
|
593
|
-
* The
|
|
594
|
-
*
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
568
|
+
* The `_deleteFixup` function is used to fix the red-black tree after a node deletion by adjusting
|
|
569
|
+
* the colors and performing rotations.
|
|
570
|
+
* @param {NODE | undefined} node - The `node` parameter represents a node in a Red-Black Tree data
|
|
571
|
+
* structure. It can be either a valid node object or `undefined`.
|
|
572
|
+
* @returns The function does not return any value. It has a return type of `void`.
|
|
573
|
+
*/
|
|
574
|
+
protected _deleteFixup(node: NODE | undefined): void {
|
|
575
|
+
// Early exit condition
|
|
576
|
+
if (!node || node === this.root || node.color === RBTNColor.BLACK) {
|
|
577
|
+
if (node) {
|
|
578
|
+
node.color = RBTNColor.BLACK; // Ensure the final node is black
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
while (node && node !== this.root && node.color === RBTNColor.BLACK) {
|
|
584
|
+
const parent: NODE | undefined = node.parent;
|
|
585
|
+
|
|
586
|
+
if (!parent) {
|
|
587
|
+
break; // Ensure the loop terminates if there's an issue with the tree structure
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (node === parent.left) {
|
|
591
|
+
let sibling = parent.right;
|
|
592
|
+
|
|
593
|
+
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
594
|
+
if (sibling?.color === RBTNColor.RED) {
|
|
595
|
+
sibling.color = RBTNColor.BLACK;
|
|
596
|
+
parent.color = RBTNColor.RED;
|
|
597
|
+
this._leftRotate(parent);
|
|
598
|
+
sibling = parent.right;
|
|
606
599
|
}
|
|
607
600
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
601
|
+
// Case 3: Sibling's left child is black
|
|
602
|
+
if ((sibling?.left?.color ?? RBTNColor.BLACK) === RBTNColor.BLACK) {
|
|
603
|
+
if (sibling) sibling.color = RBTNColor.RED;
|
|
604
|
+
node = parent;
|
|
611
605
|
} else {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (s) s.color = x.parent.color;
|
|
620
|
-
x.parent.color = RBTNColor.BLACK;
|
|
621
|
-
if (s && s.right) s.right.color = RBTNColor.BLACK;
|
|
622
|
-
this._leftRotate(x.parent);
|
|
623
|
-
x = this.root;
|
|
606
|
+
// Case 4: Adjust colors and perform a right rotation
|
|
607
|
+
if (sibling?.left) sibling.left.color = RBTNColor.BLACK;
|
|
608
|
+
if (sibling) sibling.color = parent.color;
|
|
609
|
+
parent.color = RBTNColor.BLACK;
|
|
610
|
+
this._rightRotate(parent);
|
|
611
|
+
node = this.root;
|
|
624
612
|
}
|
|
625
613
|
} else {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
614
|
+
// Symmetric case for the right child (left and right exchanged)
|
|
615
|
+
let sibling = parent.left;
|
|
616
|
+
|
|
617
|
+
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
618
|
+
if (sibling?.color === RBTNColor.RED) {
|
|
619
|
+
sibling.color = RBTNColor.BLACK;
|
|
620
|
+
if (parent) parent.color = RBTNColor.RED;
|
|
621
|
+
this._rightRotate(parent);
|
|
622
|
+
if (parent) sibling = parent.left;
|
|
632
623
|
}
|
|
633
624
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
625
|
+
// Case 3: Sibling's left child is black
|
|
626
|
+
if ((sibling?.right?.color ?? RBTNColor.BLACK) === RBTNColor.BLACK) {
|
|
627
|
+
if (sibling) sibling.color = RBTNColor.RED;
|
|
628
|
+
node = parent;
|
|
637
629
|
} else {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if (s) s.color = x.parent!.color;
|
|
646
|
-
x.parent!.color = RBTNColor.BLACK;
|
|
647
|
-
if (s && s.left) s.left.color = RBTNColor.BLACK;
|
|
648
|
-
this._rightRotate(x.parent!);
|
|
649
|
-
x = this.root;
|
|
630
|
+
// Case 4: Adjust colors and perform a left rotation
|
|
631
|
+
if (sibling?.right) sibling.right.color = RBTNColor.BLACK;
|
|
632
|
+
if (sibling) sibling.color = parent.color;
|
|
633
|
+
if (parent) parent.color = RBTNColor.BLACK;
|
|
634
|
+
this._leftRotate(parent);
|
|
635
|
+
node = this.root;
|
|
650
636
|
}
|
|
651
637
|
}
|
|
652
638
|
}
|
|
653
|
-
|
|
639
|
+
|
|
640
|
+
// Ensure that the final node (possibly the root) is black
|
|
641
|
+
if (node) {
|
|
642
|
+
node.color = RBTNColor.BLACK;
|
|
643
|
+
}
|
|
654
644
|
}
|
|
655
645
|
|
|
656
646
|
/**
|
|
@@ -662,33 +652,74 @@ export class RedBlackTree<
|
|
|
662
652
|
* Time Complexity: O(1)
|
|
663
653
|
* Space Complexity: O(1)
|
|
664
654
|
*
|
|
665
|
-
* The
|
|
666
|
-
* @param {
|
|
667
|
-
*
|
|
655
|
+
* The `_leftRotate` function performs a left rotation on a given node in a binary tree.
|
|
656
|
+
* @param {NODE | undefined} x - The parameter `x` is of type `NODE | undefined`. It represents a
|
|
657
|
+
* node in a binary tree or `undefined` if there is no node.
|
|
658
|
+
* @returns void, which means it does not return any value.
|
|
668
659
|
*/
|
|
669
|
-
protected
|
|
670
|
-
if (
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
|
|
660
|
+
protected _leftRotate(x: NODE | undefined): void {
|
|
661
|
+
if (!x || !x.right) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const y = x.right;
|
|
666
|
+
x.right = y.left;
|
|
667
|
+
|
|
668
|
+
if (this.isRealNode(y.left)) {
|
|
669
|
+
y.left.parent = x;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
y.parent = x.parent;
|
|
673
|
+
|
|
674
|
+
if (!x.parent) {
|
|
675
|
+
this._setRoot(y);
|
|
676
|
+
} else if (x === x.parent.left) {
|
|
677
|
+
x.parent.left = y;
|
|
674
678
|
} else {
|
|
675
|
-
|
|
679
|
+
x.parent.right = y;
|
|
676
680
|
}
|
|
677
|
-
|
|
681
|
+
|
|
682
|
+
y.left = x;
|
|
683
|
+
x.parent = y;
|
|
678
684
|
}
|
|
679
685
|
|
|
680
686
|
/**
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
* data structure. It is of type `NODE`, which is the type of the nodes in the data structure.
|
|
684
|
-
* @param {NODE} newNode - The `newNode` parameter is the node that will replace the `oldNode` in the
|
|
685
|
-
* data structure.
|
|
686
|
-
* @returns The method is returning the result of calling the `_replaceNode` method from the
|
|
687
|
-
* superclass, passing in the `oldNode` and `newNode` as arguments.
|
|
687
|
+
* Time Complexity: O(1)
|
|
688
|
+
* Space Complexity: O(1)
|
|
688
689
|
*/
|
|
689
|
-
protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
690
|
-
newNode.color = oldNode.color;
|
|
691
690
|
|
|
692
|
-
|
|
691
|
+
/**
|
|
692
|
+
* Time Complexity: O(1)
|
|
693
|
+
* Space Complexity: O(1)
|
|
694
|
+
*
|
|
695
|
+
* The `_rightRotate` function performs a right rotation on a given node in a binary tree.
|
|
696
|
+
* @param {NODE | undefined} y - The parameter `y` is of type `NODE | undefined`. It represents a
|
|
697
|
+
* node in a binary tree or `undefined` if there is no node.
|
|
698
|
+
* @returns void, which means it does not return any value.
|
|
699
|
+
*/
|
|
700
|
+
protected _rightRotate(y: NODE | undefined): void {
|
|
701
|
+
if (!y || !y.left) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const x = y.left;
|
|
706
|
+
y.left = x.right;
|
|
707
|
+
|
|
708
|
+
if (this.isRealNode(x.right)) {
|
|
709
|
+
x.right.parent = y;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
x.parent = y.parent;
|
|
713
|
+
|
|
714
|
+
if (!y.parent) {
|
|
715
|
+
this._setRoot(x);
|
|
716
|
+
} else if (y === y.parent.left) {
|
|
717
|
+
y.parent.left = x;
|
|
718
|
+
} else {
|
|
719
|
+
y.parent.right = x;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
x.right = y;
|
|
723
|
+
y.parent = x;
|
|
693
724
|
}
|
|
694
725
|
}
|