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