min-heap-typed 1.42.6 → 1.42.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.d.ts +5 -5
- package/dist/data-structures/binary-tree/avl-tree.js +19 -14
- package/dist/data-structures/binary-tree/binary-tree.d.ts +108 -60
- package/dist/data-structures/binary-tree/binary-tree.js +189 -89
- package/dist/data-structures/binary-tree/bst.d.ts +30 -8
- package/dist/data-structures/binary-tree/bst.js +77 -28
- package/dist/data-structures/binary-tree/rb-tree.d.ts +35 -28
- package/dist/data-structures/binary-tree/rb-tree.js +44 -45
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +7 -12
- package/dist/data-structures/binary-tree/tree-multimap.js +38 -37
- package/dist/interfaces/binary-tree.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/binary-tree.js +6 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -2
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +24 -18
- package/src/data-structures/binary-tree/binary-tree.ts +248 -142
- package/src/data-structures/binary-tree/bst.ts +88 -38
- package/src/data-structures/binary-tree/rb-tree.ts +52 -58
- package/src/data-structures/binary-tree/tree-multimap.ts +50 -54
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/types/data-structures/binary-tree/binary-tree.ts +7 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +2 -2
|
@@ -12,7 +12,8 @@ import {IBinaryTree} from '../../interfaces';
|
|
|
12
12
|
import {Queue} from '../queue';
|
|
13
13
|
|
|
14
14
|
export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extends BinaryTreeNode<V, N> {
|
|
15
|
-
override parent
|
|
15
|
+
override parent?: N ;
|
|
16
|
+
|
|
16
17
|
constructor(key: BTNKey, value?: V) {
|
|
17
18
|
super(key, value);
|
|
18
19
|
this.parent = undefined;
|
|
@@ -20,7 +21,7 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
20
21
|
this._right = undefined;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
protected override _left
|
|
24
|
+
protected override _left?: N ;
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Get the left child node.
|
|
@@ -41,7 +42,7 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
protected override _right
|
|
45
|
+
protected override _right?: N ;
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* Get the right child node.
|
|
@@ -64,8 +65,7 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
64
65
|
|
|
65
66
|
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>
|
|
66
67
|
extends BinaryTree<V, N>
|
|
67
|
-
implements IBinaryTree<V, N>
|
|
68
|
-
{
|
|
68
|
+
implements IBinaryTree<V, N> {
|
|
69
69
|
/**
|
|
70
70
|
* The constructor function initializes a binary search tree object with an optional comparator
|
|
71
71
|
* function.
|
|
@@ -82,7 +82,8 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
protected override _root?: N ;
|
|
86
87
|
|
|
87
88
|
/**
|
|
88
89
|
* Get the root node of the binary tree.
|
|
@@ -114,16 +115,13 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
114
115
|
* was not added or if the parameters were invalid, it returns undefined or undefined.
|
|
115
116
|
*/
|
|
116
117
|
override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
|
|
117
|
-
if (keyOrNode === 8) {
|
|
118
|
-
debugger
|
|
119
|
-
}
|
|
120
118
|
if (keyOrNode === null) return undefined;
|
|
121
119
|
// TODO support node as a parameter
|
|
122
|
-
let inserted:N | undefined;
|
|
123
|
-
let newNode:N | undefined;
|
|
120
|
+
let inserted: N | undefined;
|
|
121
|
+
let newNode: N | undefined;
|
|
124
122
|
if (keyOrNode instanceof BSTNode) {
|
|
125
123
|
newNode = keyOrNode;
|
|
126
|
-
} else if (
|
|
124
|
+
} else if (this.isNodeKey(keyOrNode)) {
|
|
127
125
|
newNode = this.createNode(keyOrNode, value);
|
|
128
126
|
} else {
|
|
129
127
|
newNode = undefined;
|
|
@@ -196,59 +194,60 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
196
194
|
* It can have two possible values:
|
|
197
195
|
* @returns The `addMany` function returns an array of `N`, `undefined`, or `undefined` values.
|
|
198
196
|
*/
|
|
199
|
-
|
|
200
197
|
override addMany(
|
|
201
|
-
keysOrNodes: (BTNKey |
|
|
202
|
-
data?: V[],
|
|
198
|
+
keysOrNodes: (BTNKey | N | undefined)[],
|
|
199
|
+
data?: (V | undefined)[],
|
|
203
200
|
isBalanceAdd = true,
|
|
204
201
|
iterationType = this.iterationType
|
|
205
202
|
): (N | undefined)[] {
|
|
206
203
|
// TODO this addMany function is inefficient, it should be optimized
|
|
207
|
-
function
|
|
204
|
+
function hasNoUndefined(arr: (BTNKey | N | undefined)[]): arr is (BTNKey | N)[] {
|
|
208
205
|
return arr.indexOf(undefined) === -1;
|
|
209
206
|
}
|
|
210
207
|
|
|
211
|
-
if (!isBalanceAdd || !
|
|
208
|
+
if (!isBalanceAdd || !hasNoUndefined(keysOrNodes)) {
|
|
212
209
|
return super.addMany(keysOrNodes, data).map(n => n ?? undefined);
|
|
213
210
|
}
|
|
211
|
+
|
|
214
212
|
const inserted: (N | undefined)[] = [];
|
|
215
213
|
const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(
|
|
216
214
|
(value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]
|
|
217
215
|
);
|
|
216
|
+
|
|
218
217
|
let sorted = [];
|
|
219
218
|
|
|
220
|
-
function
|
|
219
|
+
function _isNodeOrUndefinedTuple(arr: [BTNKey | N, V][]): arr is [N, V][] {
|
|
221
220
|
for (const [keyOrNode] of arr) if (keyOrNode instanceof BSTNode) return true;
|
|
222
221
|
return false;
|
|
223
222
|
}
|
|
224
223
|
|
|
225
|
-
|
|
226
|
-
for (const [keyOrNode] of arr) if (
|
|
224
|
+
const _isBinaryTreeKeyOrNullTuple = (arr: [BTNKey | N, V][]): arr is [BTNKey, V][] => {
|
|
225
|
+
for (const [keyOrNode] of arr) if (this.isNodeKey(keyOrNode)) return true;
|
|
227
226
|
return false;
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
let sortedKeysOrNodes: (number | N | undefined)[] = [],
|
|
231
230
|
sortedData: (V | undefined)[] | undefined = [];
|
|
232
231
|
|
|
233
|
-
if (
|
|
232
|
+
if (_isNodeOrUndefinedTuple(combinedArr)) {
|
|
234
233
|
sorted = combinedArr.sort((a, b) => a[0].key - b[0].key);
|
|
235
|
-
} else if (
|
|
234
|
+
} else if (_isBinaryTreeKeyOrNullTuple(combinedArr)) {
|
|
236
235
|
sorted = combinedArr.sort((a, b) => a[0] - b[0]);
|
|
237
236
|
} else {
|
|
238
237
|
throw new Error('Invalid input keysOrNodes');
|
|
239
238
|
}
|
|
240
239
|
sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);
|
|
241
240
|
sortedData = sorted.map(([, value]) => value);
|
|
242
|
-
const
|
|
241
|
+
const _dfs = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {
|
|
243
242
|
if (arr.length === 0) return;
|
|
244
243
|
|
|
245
244
|
const mid = Math.floor((arr.length - 1) / 2);
|
|
246
245
|
const newNode = this.add(arr[mid], data?.[mid]);
|
|
247
246
|
inserted.push(newNode);
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
_dfs(arr.slice(0, mid), data?.slice(0, mid));
|
|
248
|
+
_dfs(arr.slice(mid + 1), data?.slice(mid + 1));
|
|
250
249
|
};
|
|
251
|
-
const
|
|
250
|
+
const _iterate = () => {
|
|
252
251
|
const n = sorted.length;
|
|
253
252
|
const stack: [[number, number]] = [[0, n - 1]];
|
|
254
253
|
while (stack.length > 0) {
|
|
@@ -266,9 +265,9 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
266
265
|
}
|
|
267
266
|
};
|
|
268
267
|
if (iterationType === IterationType.RECURSIVE) {
|
|
269
|
-
|
|
268
|
+
_dfs(sortedKeysOrNodes, sortedData);
|
|
270
269
|
} else {
|
|
271
|
-
|
|
270
|
+
_iterate();
|
|
272
271
|
}
|
|
273
272
|
|
|
274
273
|
return inserted;
|
|
@@ -289,12 +288,61 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
289
288
|
* the key of the leftmost node if the comparison result is greater than, and the key of the
|
|
290
289
|
* rightmost node otherwise. If no node is found, it returns 0.
|
|
291
290
|
*/
|
|
292
|
-
lastKey(beginRoot: N | undefined = this.root, iterationType = this.iterationType): BTNKey {
|
|
291
|
+
lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.iterationType): BTNKey {
|
|
293
292
|
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
294
293
|
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
|
295
294
|
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
296
295
|
}
|
|
297
296
|
|
|
297
|
+
/**
|
|
298
|
+
* The function `getNodeByKey` searches for a node in a binary tree based on a given key, using
|
|
299
|
+
* either recursive or iterative methods.
|
|
300
|
+
* @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree.
|
|
301
|
+
* It is used to find the node with the matching key value.
|
|
302
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
303
|
+
* type of iteration to use when searching for a node in the binary tree. It can have two possible
|
|
304
|
+
* values:
|
|
305
|
+
* @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
|
|
306
|
+
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
307
|
+
*/
|
|
308
|
+
override getNodeByKey(key: BTNKey, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
309
|
+
if (!this.root) return undefined;
|
|
310
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
311
|
+
const _dfs = (cur: N): N | undefined => {
|
|
312
|
+
if (cur.key === key) return cur;
|
|
313
|
+
if (!cur.left && !cur.right) return;
|
|
314
|
+
|
|
315
|
+
if (this._compare(cur.key, key) === CP.gt && cur.left) return _dfs(cur.left);
|
|
316
|
+
if (this._compare(cur.key, key) === CP.lt && cur.right) return _dfs(cur.right);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
return _dfs(this.root);
|
|
320
|
+
} else {
|
|
321
|
+
const queue = new Queue<N>([this.root]);
|
|
322
|
+
while (queue.size > 0) {
|
|
323
|
+
const cur = queue.shift();
|
|
324
|
+
if (cur) {
|
|
325
|
+
if (this._compare(cur.key, key) === CP.eq) return cur;
|
|
326
|
+
if (this._compare(cur.key, key) === CP.gt) cur.left && queue.push(cur.left);
|
|
327
|
+
if (this._compare(cur.key, key) === CP.lt) cur.right && queue.push(cur.right);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* The function `ensureNotKey` returns the node corresponding to the given key if it is a node key,
|
|
335
|
+
* otherwise it returns the key itself.
|
|
336
|
+
* @param {BTNKey | N | undefined} key - The `key` parameter can be of type `BTNKey`, `N`, or
|
|
337
|
+
* `undefined`.
|
|
338
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
339
|
+
* type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`.
|
|
340
|
+
* @returns either a node object (N) or undefined.
|
|
341
|
+
*/
|
|
342
|
+
override ensureNotKey(key: BTNKey | N | undefined, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
343
|
+
return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
344
|
+
}
|
|
345
|
+
|
|
298
346
|
/**
|
|
299
347
|
* The function `getNodes` retrieves nodes from a binary tree based on a given node property or key,
|
|
300
348
|
* using either recursive or iterative traversal.
|
|
@@ -303,7 +351,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
303
351
|
* generic type `N`.
|
|
304
352
|
* @param callback - The `callback` parameter is a function that takes a node as input and returns a
|
|
305
353
|
* value. This value is compared with the `nodeProperty` parameter to determine if the node should be
|
|
306
|
-
* included in the result. The default value for `callback` is `this.
|
|
354
|
+
* included in the result. The default value for `callback` is `this._defaultOneParamCallback`, which is
|
|
307
355
|
* a
|
|
308
356
|
* @param [onlyOne=false] - A boolean value indicating whether to stop the traversal after finding
|
|
309
357
|
* the first node that matches the nodeProperty. If set to true, the function will return an array
|
|
@@ -318,11 +366,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
318
366
|
*/
|
|
319
367
|
override getNodes<C extends BTNCallback<N>>(
|
|
320
368
|
identifier: ReturnType<C> | undefined,
|
|
321
|
-
callback: C = this.
|
|
369
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
322
370
|
onlyOne = false,
|
|
323
|
-
beginRoot: N | undefined = this.root,
|
|
371
|
+
beginRoot: BTNKey | N | undefined = this.root,
|
|
324
372
|
iterationType = this.iterationType
|
|
325
373
|
): N[] {
|
|
374
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
326
375
|
if (!beginRoot) return [];
|
|
327
376
|
const ans: N[] = [];
|
|
328
377
|
|
|
@@ -336,7 +385,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
336
385
|
|
|
337
386
|
if (!cur.left && !cur.right) return;
|
|
338
387
|
// TODO potential bug
|
|
339
|
-
if (callback === this.
|
|
388
|
+
if (callback === this._defaultOneParamCallback) {
|
|
340
389
|
if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && _traverse(cur.left);
|
|
341
390
|
if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && _traverse(cur.right);
|
|
342
391
|
} else {
|
|
@@ -357,7 +406,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
357
406
|
if (onlyOne) return ans;
|
|
358
407
|
}
|
|
359
408
|
// TODO potential bug
|
|
360
|
-
if (callback === this.
|
|
409
|
+
if (callback === this._defaultOneParamCallback) {
|
|
361
410
|
if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && queue.push(cur.left);
|
|
362
411
|
if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && queue.push(cur.right);
|
|
363
412
|
} else {
|
|
@@ -391,17 +440,18 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
391
440
|
* @returns The function `lesserOrGreaterTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
|
|
392
441
|
*/
|
|
393
442
|
lesserOrGreaterTraverse<C extends BTNCallback<N>>(
|
|
394
|
-
callback: C = this.
|
|
443
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
395
444
|
lesserOrGreater: CP = CP.lt,
|
|
396
445
|
targetNode: BTNKey | N | undefined = this.root,
|
|
397
446
|
iterationType = this.iterationType
|
|
398
447
|
): ReturnType<C>[] {
|
|
399
|
-
|
|
448
|
+
targetNode = this.ensureNotKey(targetNode);
|
|
400
449
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
401
450
|
if (!targetNode) return ans;
|
|
402
|
-
const targetKey = targetNode.key;
|
|
403
451
|
if (!this.root) return ans;
|
|
404
452
|
|
|
453
|
+
const targetKey = targetNode.key;
|
|
454
|
+
|
|
405
455
|
if (iterationType === IterationType.RECURSIVE) {
|
|
406
456
|
const _traverse = (cur: N) => {
|
|
407
457
|
const compared = this._compare(cur.key, targetKey);
|
|
@@ -509,7 +559,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
509
559
|
} else {
|
|
510
560
|
const stack: N[] = [];
|
|
511
561
|
let node: N | undefined = this.root,
|
|
512
|
-
last:N | undefined = undefined;
|
|
562
|
+
last: N | undefined = undefined;
|
|
513
563
|
const depths: Map<N, number> = new Map();
|
|
514
564
|
|
|
515
565
|
while (stack.length > 0 || node) {
|
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
BiTreeDeleteResult,
|
|
11
11
|
BTNCallback,
|
|
12
12
|
BTNKey,
|
|
13
13
|
IterationType,
|
|
14
14
|
RBTNColor,
|
|
15
|
-
|
|
15
|
+
RedBlackTreeNodeNested,
|
|
16
16
|
RBTreeOptions
|
|
17
17
|
} from '../../types';
|
|
18
18
|
import {BST, BSTNode} from "./bst";
|
|
19
19
|
import {IBinaryTree} from "../../interfaces";
|
|
20
20
|
import {BinaryTreeNode} from "./binary-tree";
|
|
21
21
|
|
|
22
|
-
export class
|
|
22
|
+
export class RedBlackTreeNode<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTreeNodeNested<V>> extends BSTNode<V, N> {
|
|
23
23
|
color: RBTNColor;
|
|
24
24
|
constructor(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK) {
|
|
25
25
|
super(key, value);
|
|
@@ -34,7 +34,7 @@ export class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V
|
|
|
34
34
|
* 4. Red nodes must have black children.
|
|
35
35
|
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
36
36
|
*/
|
|
37
|
-
export class RedBlackTree<V = any, N extends
|
|
37
|
+
export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTreeNode<V, RedBlackTreeNodeNested<V>>>
|
|
38
38
|
extends BST<V, N>
|
|
39
39
|
implements IBinaryTree<V, N>
|
|
40
40
|
{
|
|
@@ -56,13 +56,21 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
56
56
|
return this._size;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
NIL: N = new
|
|
59
|
+
NIL: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* The `add` function adds a new node to a Red-Black Tree data structure.
|
|
63
|
+
* @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the
|
|
64
|
+
* following types:
|
|
65
|
+
* @param {V} [value] - The `value` parameter is an optional value that can be associated with the
|
|
66
|
+
* key in the node being added to the Red-Black Tree.
|
|
67
|
+
* @returns The method returns either a node (`N`) or `undefined`.
|
|
68
|
+
*/
|
|
61
69
|
override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
|
|
62
70
|
let node: N;
|
|
63
|
-
if (
|
|
71
|
+
if (this.isNodeKey(keyOrNode)) {
|
|
64
72
|
node = this.createNode(keyOrNode, value, RBTNColor.RED);
|
|
65
|
-
} else if(keyOrNode instanceof
|
|
73
|
+
} else if(keyOrNode instanceof RedBlackTreeNode) {
|
|
66
74
|
node = keyOrNode;
|
|
67
75
|
} else if (keyOrNode === null) {
|
|
68
76
|
return;
|
|
@@ -112,15 +120,26 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
|
|
115
|
-
return new
|
|
123
|
+
return new RedBlackTreeNode<V, N>(key, value, color) as N;
|
|
116
124
|
}
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The `delete` function removes a node from a binary tree based on a given identifier and updates
|
|
128
|
+
* the tree accordingly.
|
|
129
|
+
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the value
|
|
130
|
+
* that you want to use to identify the node that you want to delete from the binary tree. It can be
|
|
131
|
+
* of any type that is returned by the callback function `C`. It can also be `null` or `undefined` if
|
|
132
|
+
* you don't want to
|
|
133
|
+
* @param {C} callback - The `callback` parameter is a function that takes a node of type `N` and
|
|
134
|
+
* returns a value of type `ReturnType<C>`. It is used to determine if a node should be deleted based
|
|
135
|
+
* on its identifier. The `callback` function is optional and defaults to `this._defaultOneParam
|
|
136
|
+
* @returns an array of `BiTreeDeleteResult<N>`.
|
|
137
|
+
*/
|
|
119
138
|
delete<C extends BTNCallback<N>>(
|
|
120
139
|
identifier: ReturnType<C> | null | undefined,
|
|
121
|
-
callback: C = this.
|
|
122
|
-
):
|
|
123
|
-
const ans:
|
|
140
|
+
callback: C = this._defaultOneParamCallback as C
|
|
141
|
+
): BiTreeDeleteResult<N>[] {
|
|
142
|
+
const ans: BiTreeDeleteResult<N>[] = [];
|
|
124
143
|
if (identifier === null) return ans;
|
|
125
144
|
const helper = (node: N | undefined): void => {
|
|
126
145
|
let z: N = this.NIL;
|
|
@@ -151,7 +170,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
151
170
|
x = z.left;
|
|
152
171
|
this._rbTransplant(z, z.left!);
|
|
153
172
|
} else {
|
|
154
|
-
y = this.getLeftMost(z.right)
|
|
173
|
+
y = this.getLeftMost(z.right)!;
|
|
155
174
|
yOriginalColor = y.color;
|
|
156
175
|
x = y.right;
|
|
157
176
|
if (y.parent === z) {
|
|
@@ -177,7 +196,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
177
196
|
return ans;
|
|
178
197
|
}
|
|
179
198
|
|
|
180
|
-
|
|
199
|
+
override isRealNode(node: N | undefined): node is N {
|
|
181
200
|
return node !== this.NIL && node !== undefined;
|
|
182
201
|
}
|
|
183
202
|
|
|
@@ -210,7 +229,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
210
229
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
211
230
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
212
231
|
* whether the node matches the criteria or not. The default callback function
|
|
213
|
-
* (`this.
|
|
232
|
+
* (`this._defaultOneParamCallback`) is used if no callback function is
|
|
214
233
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
215
234
|
* the root node from which the search should begin.
|
|
216
235
|
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
@@ -219,48 +238,23 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
219
238
|
*/
|
|
220
239
|
getNode<C extends BTNCallback<N>>(
|
|
221
240
|
identifier: ReturnType<C> | undefined,
|
|
222
|
-
callback: C = this.
|
|
223
|
-
beginRoot = this.root,
|
|
241
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
242
|
+
beginRoot: BTNKey | N | undefined = this.root,
|
|
224
243
|
iterationType = this.iterationType
|
|
225
244
|
): N | null | undefined {
|
|
226
245
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
227
|
-
|
|
246
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
228
247
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
229
248
|
}
|
|
230
249
|
|
|
231
|
-
/**
|
|
232
|
-
* The function returns the leftmost node in a red-black tree.
|
|
233
|
-
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode, which represents a node in
|
|
234
|
-
* a Red-Black Tree.
|
|
235
|
-
* @returns The leftmost node in the given RBTreeNode.
|
|
236
|
-
*/
|
|
237
|
-
getLeftMost(node: N = this.root): N {
|
|
238
|
-
while (node.left !== undefined && node.left !== this.NIL) {
|
|
239
|
-
node = node.left;
|
|
240
|
-
}
|
|
241
|
-
return node;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* The function returns the rightmost node in a red-black tree.
|
|
246
|
-
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
|
|
247
|
-
* @returns the rightmost node in a red-black tree.
|
|
248
|
-
*/
|
|
249
|
-
getRightMost(node: N): N {
|
|
250
|
-
while (node.right !== undefined && node.right !== this.NIL) {
|
|
251
|
-
node = node.right;
|
|
252
|
-
}
|
|
253
|
-
return node;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
250
|
/**
|
|
257
251
|
* The function returns the successor of a given node in a red-black tree.
|
|
258
|
-
* @param {
|
|
259
|
-
* @returns the successor of the given
|
|
252
|
+
* @param {RedBlackTreeNode} x - RedBlackTreeNode - The node for which we want to find the successor.
|
|
253
|
+
* @returns the successor of the given RedBlackTreeNode.
|
|
260
254
|
*/
|
|
261
|
-
getSuccessor(x: N): N | undefined {
|
|
255
|
+
override getSuccessor(x: N): N | undefined {
|
|
262
256
|
if (x.right !== this.NIL) {
|
|
263
|
-
return this.getLeftMost(x.right);
|
|
257
|
+
return this.getLeftMost(x.right) ?? undefined;
|
|
264
258
|
}
|
|
265
259
|
|
|
266
260
|
let y: N | undefined = x.parent;
|
|
@@ -273,13 +267,13 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
273
267
|
|
|
274
268
|
/**
|
|
275
269
|
* The function returns the predecessor of a given node in a red-black tree.
|
|
276
|
-
* @param {
|
|
270
|
+
* @param {RedBlackTreeNode} x - The parameter `x` is of type `RedBlackTreeNode`, which represents a node in a
|
|
277
271
|
* Red-Black Tree.
|
|
278
|
-
* @returns the predecessor of the given
|
|
272
|
+
* @returns the predecessor of the given RedBlackTreeNode 'x'.
|
|
279
273
|
*/
|
|
280
|
-
getPredecessor(x: N): N {
|
|
274
|
+
override getPredecessor(x: N): N {
|
|
281
275
|
if (x.left !== this.NIL) {
|
|
282
|
-
return this.getRightMost(x.left!)
|
|
276
|
+
return this.getRightMost(x.left!)!;
|
|
283
277
|
}
|
|
284
278
|
|
|
285
279
|
let y: N | undefined = x.parent;
|
|
@@ -305,7 +299,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
305
299
|
|
|
306
300
|
/**
|
|
307
301
|
* The function performs a left rotation on a red-black tree node.
|
|
308
|
-
* @param {
|
|
302
|
+
* @param {RedBlackTreeNode} x - The parameter `x` is a RedBlackTreeNode object.
|
|
309
303
|
*/
|
|
310
304
|
protected _leftRotate(x: N): void {
|
|
311
305
|
if (x.right) {
|
|
@@ -329,7 +323,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
329
323
|
|
|
330
324
|
/**
|
|
331
325
|
* The function performs a right rotation on a red-black tree node.
|
|
332
|
-
* @param {
|
|
326
|
+
* @param {RedBlackTreeNode} x - x is a RedBlackTreeNode, which represents the node that needs to be right
|
|
333
327
|
* rotated.
|
|
334
328
|
*/
|
|
335
329
|
protected _rightRotate(x: N): void {
|
|
@@ -354,7 +348,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
354
348
|
|
|
355
349
|
/**
|
|
356
350
|
* The _fixDelete function is used to rebalance the Red-Black Tree after a node deletion.
|
|
357
|
-
* @param {
|
|
351
|
+
* @param {RedBlackTreeNode} x - The parameter `x` is of type `RedBlackTreeNode`, which represents a node in a
|
|
358
352
|
* red-black tree.
|
|
359
353
|
*/
|
|
360
354
|
protected _fixDelete(x: N): void {
|
|
@@ -419,8 +413,8 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
419
413
|
|
|
420
414
|
/**
|
|
421
415
|
* The function `_rbTransplant` replaces one node in a red-black tree with another node.
|
|
422
|
-
* @param {
|
|
423
|
-
* @param {
|
|
416
|
+
* @param {RedBlackTreeNode} u - The parameter "u" represents a RedBlackTreeNode object.
|
|
417
|
+
* @param {RedBlackTreeNode} v - The parameter "v" is a RedBlackTreeNode object.
|
|
424
418
|
*/
|
|
425
419
|
protected _rbTransplant(u: N, v: N): void {
|
|
426
420
|
if (u.parent === undefined) {
|
|
@@ -435,7 +429,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|
|
435
429
|
|
|
436
430
|
/**
|
|
437
431
|
* The `_fixInsert` function is used to fix the red-black tree after an insertion operation.
|
|
438
|
-
* @param {
|
|
432
|
+
* @param {RedBlackTreeNode} k - The parameter `k` is a RedBlackTreeNode object, which represents a node in a
|
|
439
433
|
* red-black tree.
|
|
440
434
|
*/
|
|
441
435
|
protected _fixInsert(k: N): void {
|