graph-typed 1.50.6 → 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 +13 -9
- package/dist/data-structures/binary-tree/bst.js +17 -17
- package/dist/data-structures/binary-tree/rb-tree.d.ts +2 -8
- package/dist/data-structures/binary-tree/rb-tree.js +7 -16
- 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 +12 -10
- package/src/data-structures/binary-tree/bst.ts +18 -18
- package/src/data-structures/binary-tree/rb-tree.ts +11 -22
- package/src/types/common.ts +7 -0
|
@@ -46,6 +46,7 @@ export declare class AVLTreeMultiMap<K = any, V = any, NODE extends AVLTreeMulti
|
|
|
46
46
|
* @returns the sum of the count property of all nodes in the tree.
|
|
47
47
|
*/
|
|
48
48
|
get count(): number;
|
|
49
|
+
getMutableCount(): number;
|
|
49
50
|
/**
|
|
50
51
|
* The function creates a new BSTNode with the given key, value, and count.
|
|
51
52
|
* @param {K} key - The key parameter is the unique identifier for the binary tree node. It is used to
|
|
@@ -53,6 +53,9 @@ class AVLTreeMultiMap extends avl_tree_1.AVLTree {
|
|
|
53
53
|
* @returns the sum of the count property of all nodes in the tree.
|
|
54
54
|
*/
|
|
55
55
|
get count() {
|
|
56
|
+
return this._count;
|
|
57
|
+
}
|
|
58
|
+
getMutableCount() {
|
|
56
59
|
let sum = 0;
|
|
57
60
|
this.dfs(node => (sum += node.count));
|
|
58
61
|
return sum;
|
|
@@ -821,7 +821,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
821
821
|
*/
|
|
822
822
|
getHeight(beginRoot = this.root, iterationType = this.iterationType) {
|
|
823
823
|
beginRoot = this.ensureNode(beginRoot);
|
|
824
|
-
if (!beginRoot)
|
|
824
|
+
if (!this.isRealNode(beginRoot))
|
|
825
825
|
return -1;
|
|
826
826
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
827
827
|
const _getMaxHeight = (cur) => {
|
|
@@ -871,9 +871,9 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
871
871
|
return -1;
|
|
872
872
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
873
873
|
const _getMinHeight = (cur) => {
|
|
874
|
-
if (!cur)
|
|
874
|
+
if (!this.isRealNode(cur))
|
|
875
875
|
return 0;
|
|
876
|
-
if (!cur.left && !cur.right)
|
|
876
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
877
877
|
return 0;
|
|
878
878
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
879
879
|
const rightMinHeight = _getMinHeight(cur.right);
|
|
@@ -886,17 +886,17 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
886
886
|
let node = beginRoot, last = null;
|
|
887
887
|
const depths = new Map();
|
|
888
888
|
while (stack.length > 0 || node) {
|
|
889
|
-
if (node) {
|
|
889
|
+
if (this.isRealNode(node)) {
|
|
890
890
|
stack.push(node);
|
|
891
891
|
node = node.left;
|
|
892
892
|
}
|
|
893
893
|
else {
|
|
894
894
|
node = stack[stack.length - 1];
|
|
895
|
-
if (!node.right || last === node.right) {
|
|
895
|
+
if (!this.isRealNode(node.right) || last === node.right) {
|
|
896
896
|
node = stack.pop();
|
|
897
|
-
if (node) {
|
|
898
|
-
const leftMinHeight = node.left ? (_a = depths.get(node.left)) !== null && _a !== void 0 ? _a : -1 : -1;
|
|
899
|
-
const rightMinHeight = node.right ? (_b = depths.get(node.right)) !== null && _b !== void 0 ? _b : -1 : -1;
|
|
897
|
+
if (this.isRealNode(node)) {
|
|
898
|
+
const leftMinHeight = this.isRealNode(node.left) ? (_a = depths.get(node.left)) !== null && _a !== void 0 ? _a : -1 : -1;
|
|
899
|
+
const rightMinHeight = this.isRealNode(node.right) ? (_b = depths.get(node.right)) !== null && _b !== void 0 ? _b : -1 : -1;
|
|
900
900
|
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
|
|
901
901
|
last = node;
|
|
902
902
|
node = null;
|
|
@@ -962,8 +962,10 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
962
962
|
* is no leftmost node, it returns `null` or `undefined` depending on the input.
|
|
963
963
|
*/
|
|
964
964
|
getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
|
|
965
|
+
if (this.isNIL(beginRoot))
|
|
966
|
+
return beginRoot;
|
|
965
967
|
beginRoot = this.ensureNode(beginRoot);
|
|
966
|
-
if (!beginRoot)
|
|
968
|
+
if (!this.isRealNode(beginRoot))
|
|
967
969
|
return beginRoot;
|
|
968
970
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
969
971
|
const _traverse = (cur) => {
|
|
@@ -1003,6 +1005,8 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1003
1005
|
* is no rightmost node, it returns `null` or `undefined`, depending on the input.
|
|
1004
1006
|
*/
|
|
1005
1007
|
getRightMost(beginRoot = this.root, iterationType = this.iterationType) {
|
|
1008
|
+
if (this.isNIL(beginRoot))
|
|
1009
|
+
return beginRoot;
|
|
1006
1010
|
// TODO support get right most by passing key in
|
|
1007
1011
|
beginRoot = this.ensureNode(beginRoot);
|
|
1008
1012
|
if (!beginRoot)
|
|
@@ -362,17 +362,17 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
362
362
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
363
363
|
*/
|
|
364
364
|
getNodeByKey(key, iterationType = types_1.IterationType.ITERATIVE) {
|
|
365
|
-
if (!this.root)
|
|
365
|
+
if (!this.isRealNode(this.root))
|
|
366
366
|
return undefined;
|
|
367
367
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
368
368
|
const _dfs = (cur) => {
|
|
369
369
|
if (cur.key === key)
|
|
370
370
|
return cur;
|
|
371
|
-
if (!cur.left && !cur.right)
|
|
371
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
372
372
|
return;
|
|
373
|
-
if (this._compare(cur.key, key) === types_1.CP.gt && cur.left)
|
|
373
|
+
if (this._compare(cur.key, key) === types_1.CP.gt && this.isRealNode(cur.left))
|
|
374
374
|
return _dfs(cur.left);
|
|
375
|
-
if (this._compare(cur.key, key) === types_1.CP.lt && cur.right)
|
|
375
|
+
if (this._compare(cur.key, key) === types_1.CP.lt && this.isRealNode(cur.right))
|
|
376
376
|
return _dfs(cur.right);
|
|
377
377
|
};
|
|
378
378
|
return _dfs(this.root);
|
|
@@ -381,13 +381,13 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
381
381
|
const queue = new queue_1.Queue([this.root]);
|
|
382
382
|
while (queue.size > 0) {
|
|
383
383
|
const cur = queue.shift();
|
|
384
|
-
if (cur) {
|
|
384
|
+
if (this.isRealNode(cur)) {
|
|
385
385
|
if (this._compare(cur.key, key) === types_1.CP.eq)
|
|
386
386
|
return cur;
|
|
387
387
|
if (this._compare(cur.key, key) === types_1.CP.gt)
|
|
388
|
-
cur.left && queue.push(cur.left);
|
|
388
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
389
389
|
if (this._compare(cur.key, key) === types_1.CP.lt)
|
|
390
|
-
cur.right && queue.push(cur.right);
|
|
390
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
393
|
}
|
|
@@ -433,18 +433,18 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
433
433
|
if (onlyOne)
|
|
434
434
|
return;
|
|
435
435
|
}
|
|
436
|
-
if (!cur.left && !cur.right)
|
|
436
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
437
437
|
return;
|
|
438
438
|
// TODO potential bug
|
|
439
439
|
if (callback === this._defaultOneParamCallback) {
|
|
440
440
|
if (this._compare(cur.key, identifier) === types_1.CP.gt)
|
|
441
|
-
cur.left && _traverse(cur.left);
|
|
441
|
+
this.isRealNode(cur.left) && _traverse(cur.left);
|
|
442
442
|
if (this._compare(cur.key, identifier) === types_1.CP.lt)
|
|
443
|
-
cur.right && _traverse(cur.right);
|
|
443
|
+
this.isRealNode(cur.right) && _traverse(cur.right);
|
|
444
444
|
}
|
|
445
445
|
else {
|
|
446
|
-
cur.left && _traverse(cur.left);
|
|
447
|
-
cur.right && _traverse(cur.right);
|
|
446
|
+
this.isRealNode(cur.left) && _traverse(cur.left);
|
|
447
|
+
this.isRealNode(cur.right) && _traverse(cur.right);
|
|
448
448
|
}
|
|
449
449
|
};
|
|
450
450
|
_traverse(beginRoot);
|
|
@@ -453,7 +453,7 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
453
453
|
const queue = new queue_1.Queue([beginRoot]);
|
|
454
454
|
while (queue.size > 0) {
|
|
455
455
|
const cur = queue.shift();
|
|
456
|
-
if (cur) {
|
|
456
|
+
if (this.isRealNode(cur)) {
|
|
457
457
|
const callbackResult = callback(cur);
|
|
458
458
|
if (callbackResult === identifier) {
|
|
459
459
|
ans.push(cur);
|
|
@@ -463,13 +463,13 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
463
463
|
// TODO potential bug
|
|
464
464
|
if (callback === this._defaultOneParamCallback) {
|
|
465
465
|
if (this._compare(cur.key, identifier) === types_1.CP.gt)
|
|
466
|
-
cur.left && queue.push(cur.left);
|
|
466
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
467
467
|
if (this._compare(cur.key, identifier) === types_1.CP.lt)
|
|
468
|
-
cur.right && queue.push(cur.right);
|
|
468
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
469
469
|
}
|
|
470
470
|
else {
|
|
471
|
-
cur.left && queue.push(cur.left);
|
|
472
|
-
cur.right && queue.push(cur.right);
|
|
471
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
472
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BinaryTreeDeleteResult, BSTNKeyOrNode, BTNCallback, KeyOrNodeOrEntry, RBTreeOptions, RedBlackTreeNested, RedBlackTreeNodeNested } from '../../types';
|
|
2
|
-
import { RBTNColor } from '../../types';
|
|
2
|
+
import { CRUD, RBTNColor } from '../../types';
|
|
3
3
|
import { BST, BSTNode } from './bst';
|
|
4
4
|
import { IBinaryTree } from '../../interfaces';
|
|
5
5
|
export declare class RedBlackTreeNode<K = any, V = any, NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNodeNested<K, V>> extends BSTNode<K, V, NODE> {
|
|
@@ -51,12 +51,6 @@ export declare class RedBlackTree<K = any, V = any, NODE extends RedBlackTreeNod
|
|
|
51
51
|
* @returns The root node of the tree structure, or undefined if there is no root node.
|
|
52
52
|
*/
|
|
53
53
|
get root(): NODE | undefined;
|
|
54
|
-
protected _size: number;
|
|
55
|
-
/**
|
|
56
|
-
* The function returns the size of an object.
|
|
57
|
-
* @returns The size of the object, which is a number.
|
|
58
|
-
*/
|
|
59
|
-
get size(): number;
|
|
60
54
|
/**
|
|
61
55
|
* The function creates a new Red-Black Tree node with the specified key, value, and color.
|
|
62
56
|
* @param {K} key - The key parameter represents the key of the node being created. It is of type K,
|
|
@@ -236,7 +230,7 @@ export declare class RedBlackTree<K = any, V = any, NODE extends RedBlackTreeNod
|
|
|
236
230
|
* node in the tree.
|
|
237
231
|
* @returns {'inserted' | 'updated'} - The result of the insertion.
|
|
238
232
|
*/
|
|
239
|
-
protected _insert(node: NODE):
|
|
233
|
+
protected _insert(node: NODE): CRUD;
|
|
240
234
|
/**
|
|
241
235
|
* Time Complexity: O(1)
|
|
242
236
|
* Space Complexity: O(1)
|
|
@@ -49,7 +49,6 @@ class RedBlackTree extends bst_1.BST {
|
|
|
49
49
|
constructor(keysOrNodesOrEntries = [], options) {
|
|
50
50
|
super([], options);
|
|
51
51
|
this._SENTINEL = new RedBlackTreeNode(NaN);
|
|
52
|
-
this._size = 0;
|
|
53
52
|
this._root = this.SENTINEL;
|
|
54
53
|
if (keysOrNodesOrEntries) {
|
|
55
54
|
this.addMany(keysOrNodesOrEntries);
|
|
@@ -69,13 +68,6 @@ class RedBlackTree extends bst_1.BST {
|
|
|
69
68
|
get root() {
|
|
70
69
|
return this._root;
|
|
71
70
|
}
|
|
72
|
-
/**
|
|
73
|
-
* The function returns the size of an object.
|
|
74
|
-
* @returns The size of the object, which is a number.
|
|
75
|
-
*/
|
|
76
|
-
get size() {
|
|
77
|
-
return this._size;
|
|
78
|
-
}
|
|
79
71
|
/**
|
|
80
72
|
* The function creates a new Red-Black Tree node with the specified key, value, and color.
|
|
81
73
|
* @param {K} key - The key parameter represents the key of the node being created. It is of type K,
|
|
@@ -170,7 +162,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
170
162
|
* @returns a boolean value.
|
|
171
163
|
*/
|
|
172
164
|
isRealNode(node) {
|
|
173
|
-
if (node === this.
|
|
165
|
+
if (node === this.SENTINEL || node === undefined)
|
|
174
166
|
return false;
|
|
175
167
|
return node instanceof RedBlackTreeNode;
|
|
176
168
|
}
|
|
@@ -203,8 +195,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
203
195
|
var _a;
|
|
204
196
|
if (identifier instanceof RedBlackTreeNode)
|
|
205
197
|
callback = (node => node);
|
|
206
|
-
|
|
207
|
-
return (_a = this.getNodes(identifier, callback, true, beginRoot, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
|
|
198
|
+
return (_a = super.getNodes(identifier, callback, true, beginRoot, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
|
|
208
199
|
}
|
|
209
200
|
/**
|
|
210
201
|
* Time Complexity: O(1)
|
|
@@ -218,8 +209,8 @@ class RedBlackTree extends bst_1.BST {
|
|
|
218
209
|
* size counter to zero.
|
|
219
210
|
*/
|
|
220
211
|
clear() {
|
|
212
|
+
super.clear();
|
|
221
213
|
this._root = this.SENTINEL;
|
|
222
|
-
this._size = 0;
|
|
223
214
|
}
|
|
224
215
|
/**
|
|
225
216
|
* Time Complexity: O(log n)
|
|
@@ -243,7 +234,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
243
234
|
if (!this.isRealNode(newNode))
|
|
244
235
|
return false;
|
|
245
236
|
const insertStatus = this._insert(newNode);
|
|
246
|
-
if (insertStatus ===
|
|
237
|
+
if (insertStatus === types_1.CRUD.CREATED) {
|
|
247
238
|
// Ensure the root is black
|
|
248
239
|
if (this.isRealNode(this._root)) {
|
|
249
240
|
this._root.color = types_1.RBTNColor.BLACK;
|
|
@@ -255,7 +246,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
255
246
|
return true;
|
|
256
247
|
}
|
|
257
248
|
else
|
|
258
|
-
return insertStatus ===
|
|
249
|
+
return insertStatus === types_1.CRUD.UPDATED;
|
|
259
250
|
}
|
|
260
251
|
/**
|
|
261
252
|
* Time Complexity: O(log n)
|
|
@@ -388,7 +379,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
388
379
|
}
|
|
389
380
|
else {
|
|
390
381
|
this._replaceNode(current, node);
|
|
391
|
-
return
|
|
382
|
+
return types_1.CRUD.UPDATED;
|
|
392
383
|
}
|
|
393
384
|
}
|
|
394
385
|
node.parent = parent;
|
|
@@ -405,7 +396,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
405
396
|
node.right = this.SENTINEL;
|
|
406
397
|
node.color = types_1.RBTNColor.RED;
|
|
407
398
|
this._insertFixup(node);
|
|
408
|
-
return
|
|
399
|
+
return types_1.CRUD.CREATED;
|
|
409
400
|
}
|
|
410
401
|
/**
|
|
411
402
|
* Time Complexity: O(1)
|
package/dist/types/common.d.ts
CHANGED
package/dist/types/common.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FamilyPosition = exports.IterationType = exports.CP = exports.BSTVariant = void 0;
|
|
3
|
+
exports.CRUD = exports.FamilyPosition = exports.IterationType = exports.CP = exports.BSTVariant = void 0;
|
|
4
4
|
var BSTVariant;
|
|
5
5
|
(function (BSTVariant) {
|
|
6
6
|
BSTVariant["STANDARD"] = "STANDARD";
|
|
@@ -33,3 +33,10 @@ var FamilyPosition;
|
|
|
33
33
|
FamilyPosition["ISOLATED"] = "ISOLATED";
|
|
34
34
|
FamilyPosition["MAL_NODE"] = "MAL_NODE";
|
|
35
35
|
})(FamilyPosition = exports.FamilyPosition || (exports.FamilyPosition = {}));
|
|
36
|
+
var CRUD;
|
|
37
|
+
(function (CRUD) {
|
|
38
|
+
CRUD["CREATED"] = "CREATED";
|
|
39
|
+
CRUD["READ"] = "READ";
|
|
40
|
+
CRUD["UPDATED"] = "UPDATED";
|
|
41
|
+
CRUD["DELETED"] = "DELETED";
|
|
42
|
+
})(CRUD = exports.CRUD || (exports.CRUD = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graph-typed",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.7",
|
|
4
4
|
"description": "Graph. Javascript & Typescript Data Structure.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -136,6 +136,6 @@
|
|
|
136
136
|
"typescript": "^4.9.5"
|
|
137
137
|
},
|
|
138
138
|
"dependencies": {
|
|
139
|
-
"data-structure-typed": "^1.50.
|
|
139
|
+
"data-structure-typed": "^1.50.7"
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -83,6 +83,10 @@ export class AVLTreeMultiMap<
|
|
|
83
83
|
* @returns the sum of the count property of all nodes in the tree.
|
|
84
84
|
*/
|
|
85
85
|
get count(): number {
|
|
86
|
+
return this._count;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
getMutableCount(): number {
|
|
86
90
|
let sum = 0;
|
|
87
91
|
this.dfs(node => (sum += node.count));
|
|
88
92
|
return sum;
|
|
@@ -414,7 +418,7 @@ export class AVLTreeMultiMap<
|
|
|
414
418
|
* @returns The method is returning the result of calling the `_replaceNode` method from the
|
|
415
419
|
* superclass, after updating the `count` property of the `newNode` object.
|
|
416
420
|
*/
|
|
417
|
-
protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
421
|
+
protected override _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
418
422
|
newNode.count = oldNode.count + newNode.count;
|
|
419
423
|
return super._replaceNode(oldNode, newNode);
|
|
420
424
|
}
|
|
@@ -522,7 +522,7 @@ export class AVLTree<
|
|
|
522
522
|
* @returns the result of calling the `_replaceNode` method on the superclass, passing in the
|
|
523
523
|
* `oldNode` and `newNode` as arguments.
|
|
524
524
|
*/
|
|
525
|
-
protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
525
|
+
protected override _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
526
526
|
newNode.height = oldNode.height;
|
|
527
527
|
|
|
528
528
|
return super._replaceNode(oldNode, newNode);
|
|
@@ -1021,7 +1021,7 @@ export class BinaryTree<
|
|
|
1021
1021
|
*/
|
|
1022
1022
|
getHeight(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, iterationType = this.iterationType): number {
|
|
1023
1023
|
beginRoot = this.ensureNode(beginRoot);
|
|
1024
|
-
if (!beginRoot) return -1;
|
|
1024
|
+
if (!this.isRealNode(beginRoot)) return -1;
|
|
1025
1025
|
|
|
1026
1026
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1027
1027
|
const _getMaxHeight = (cur: NODE | null | undefined): number => {
|
|
@@ -1073,8 +1073,8 @@ export class BinaryTree<
|
|
|
1073
1073
|
|
|
1074
1074
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1075
1075
|
const _getMinHeight = (cur: NODE | null | undefined): number => {
|
|
1076
|
-
if (!cur) return 0;
|
|
1077
|
-
if (!cur.left && !cur.right) return 0;
|
|
1076
|
+
if (!this.isRealNode(cur)) return 0;
|
|
1077
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
1078
1078
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
1079
1079
|
const rightMinHeight = _getMinHeight(cur.right);
|
|
1080
1080
|
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
@@ -1088,16 +1088,16 @@ export class BinaryTree<
|
|
|
1088
1088
|
const depths: Map<NODE, number> = new Map();
|
|
1089
1089
|
|
|
1090
1090
|
while (stack.length > 0 || node) {
|
|
1091
|
-
if (node) {
|
|
1091
|
+
if (this.isRealNode(node)) {
|
|
1092
1092
|
stack.push(node);
|
|
1093
1093
|
node = node.left;
|
|
1094
1094
|
} else {
|
|
1095
1095
|
node = stack[stack.length - 1];
|
|
1096
|
-
if (!node.right || last === node.right) {
|
|
1096
|
+
if (!this.isRealNode(node.right) || last === node.right) {
|
|
1097
1097
|
node = stack.pop();
|
|
1098
|
-
if (node) {
|
|
1099
|
-
const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
|
|
1100
|
-
const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
|
|
1098
|
+
if (this.isRealNode(node)) {
|
|
1099
|
+
const leftMinHeight = this.isRealNode(node.left) ? depths.get(node.left) ?? -1 : -1;
|
|
1100
|
+
const rightMinHeight = this.isRealNode(node.right) ? depths.get(node.right) ?? -1 : -1;
|
|
1101
1101
|
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
|
|
1102
1102
|
last = node;
|
|
1103
1103
|
node = null;
|
|
@@ -1169,9 +1169,10 @@ export class BinaryTree<
|
|
|
1169
1169
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1170
1170
|
iterationType = this.iterationType
|
|
1171
1171
|
): NODE | null | undefined {
|
|
1172
|
+
if (this.isNIL(beginRoot)) return beginRoot as NODE;
|
|
1172
1173
|
beginRoot = this.ensureNode(beginRoot);
|
|
1173
1174
|
|
|
1174
|
-
if (!beginRoot) return beginRoot;
|
|
1175
|
+
if (!this.isRealNode(beginRoot)) return beginRoot;
|
|
1175
1176
|
|
|
1176
1177
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1177
1178
|
const _traverse = (cur: NODE): NODE => {
|
|
@@ -1215,6 +1216,7 @@ export class BinaryTree<
|
|
|
1215
1216
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1216
1217
|
iterationType = this.iterationType
|
|
1217
1218
|
): NODE | null | undefined {
|
|
1219
|
+
if (this.isNIL(beginRoot)) return beginRoot as NODE;
|
|
1218
1220
|
// TODO support get right most by passing key in
|
|
1219
1221
|
beginRoot = this.ensureNode(beginRoot);
|
|
1220
1222
|
if (!beginRoot) return beginRoot;
|
|
@@ -1837,7 +1839,7 @@ export class BinaryTree<
|
|
|
1837
1839
|
* following types:
|
|
1838
1840
|
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
|
1839
1841
|
*/
|
|
1840
|
-
print(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions): void {
|
|
1842
|
+
override print(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions): void {
|
|
1841
1843
|
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1842
1844
|
beginRoot = this.ensureNode(beginRoot);
|
|
1843
1845
|
if (!beginRoot) return;
|
|
@@ -426,14 +426,14 @@ export class BST<
|
|
|
426
426
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
427
427
|
*/
|
|
428
428
|
override getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined {
|
|
429
|
-
if (!this.root) return undefined;
|
|
429
|
+
if (!this.isRealNode(this.root)) return undefined;
|
|
430
430
|
if (iterationType === IterationType.RECURSIVE) {
|
|
431
431
|
const _dfs = (cur: NODE): NODE | undefined => {
|
|
432
432
|
if (cur.key === key) return cur;
|
|
433
|
-
if (!cur.left && !cur.right) return;
|
|
433
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
434
434
|
|
|
435
|
-
if (this._compare(cur.key, key) === CP.gt && cur.left) return _dfs(cur.left);
|
|
436
|
-
if (this._compare(cur.key, key) === CP.lt && cur.right) return _dfs(cur.right);
|
|
435
|
+
if (this._compare(cur.key, key) === CP.gt && this.isRealNode(cur.left)) return _dfs(cur.left);
|
|
436
|
+
if (this._compare(cur.key, key) === CP.lt && this.isRealNode(cur.right)) return _dfs(cur.right);
|
|
437
437
|
};
|
|
438
438
|
|
|
439
439
|
return _dfs(this.root);
|
|
@@ -441,10 +441,10 @@ export class BST<
|
|
|
441
441
|
const queue = new Queue<NODE>([this.root]);
|
|
442
442
|
while (queue.size > 0) {
|
|
443
443
|
const cur = queue.shift();
|
|
444
|
-
if (cur) {
|
|
444
|
+
if (this.isRealNode(cur)) {
|
|
445
445
|
if (this._compare(cur.key, key) === CP.eq) return cur;
|
|
446
|
-
if (this._compare(cur.key, key) === CP.gt) cur.left && queue.push(cur.left);
|
|
447
|
-
if (this._compare(cur.key, key) === CP.lt) cur.right && queue.push(cur.right);
|
|
446
|
+
if (this._compare(cur.key, key) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left);
|
|
447
|
+
if (this._compare(cur.key, key) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right);
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
450
|
}
|
|
@@ -497,14 +497,14 @@ export class BST<
|
|
|
497
497
|
if (onlyOne) return;
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
-
if (!cur.left && !cur.right) return;
|
|
500
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
501
501
|
// TODO potential bug
|
|
502
502
|
if (callback === this._defaultOneParamCallback) {
|
|
503
|
-
if (this._compare(cur.key, identifier as K) === CP.gt) cur.left && _traverse(cur.left);
|
|
504
|
-
if (this._compare(cur.key, identifier as K) === CP.lt) cur.right && _traverse(cur.right);
|
|
503
|
+
if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && _traverse(cur.left);
|
|
504
|
+
if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && _traverse(cur.right);
|
|
505
505
|
} else {
|
|
506
|
-
cur.left && _traverse(cur.left);
|
|
507
|
-
cur.right && _traverse(cur.right);
|
|
506
|
+
this.isRealNode(cur.left) && _traverse(cur.left);
|
|
507
|
+
this.isRealNode(cur.right) && _traverse(cur.right);
|
|
508
508
|
}
|
|
509
509
|
};
|
|
510
510
|
|
|
@@ -513,7 +513,7 @@ export class BST<
|
|
|
513
513
|
const queue = new Queue<NODE>([beginRoot]);
|
|
514
514
|
while (queue.size > 0) {
|
|
515
515
|
const cur = queue.shift();
|
|
516
|
-
if (cur) {
|
|
516
|
+
if (this.isRealNode(cur)) {
|
|
517
517
|
const callbackResult = callback(cur);
|
|
518
518
|
if (callbackResult === identifier) {
|
|
519
519
|
ans.push(cur);
|
|
@@ -521,11 +521,11 @@ export class BST<
|
|
|
521
521
|
}
|
|
522
522
|
// TODO potential bug
|
|
523
523
|
if (callback === this._defaultOneParamCallback) {
|
|
524
|
-
if (this._compare(cur.key, identifier as K) === CP.gt) cur.left && queue.push(cur.left);
|
|
525
|
-
if (this._compare(cur.key, identifier as K) === CP.lt) cur.right && queue.push(cur.right);
|
|
524
|
+
if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left);
|
|
525
|
+
if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right);
|
|
526
526
|
} else {
|
|
527
|
-
cur.left && queue.push(cur.left);
|
|
528
|
-
cur.right && queue.push(cur.right);
|
|
527
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
528
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
531
|
}
|
|
@@ -856,7 +856,7 @@ export class BST<
|
|
|
856
856
|
* @param {NODE | undefined} v - The parameter `v` is of type `NODE | undefined`. This means that it
|
|
857
857
|
* can either be an object of type `NODE` or it can be `undefined`.
|
|
858
858
|
*/
|
|
859
|
-
protected _setRoot(v: NODE | undefined) {
|
|
859
|
+
protected override _setRoot(v: NODE | undefined) {
|
|
860
860
|
if (v) {
|
|
861
861
|
v.parent = undefined;
|
|
862
862
|
}
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
RedBlackTreeNested,
|
|
8
8
|
RedBlackTreeNodeNested
|
|
9
9
|
} from '../../types';
|
|
10
|
-
import { RBTNColor } from '../../types';
|
|
10
|
+
import { CRUD, RBTNColor } from '../../types';
|
|
11
11
|
import { BST, BSTNode } from './bst';
|
|
12
12
|
import { IBinaryTree } from '../../interfaces';
|
|
13
13
|
|
|
@@ -89,26 +89,16 @@ export class RedBlackTree<
|
|
|
89
89
|
return this._SENTINEL;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
protected _root: NODE | undefined;
|
|
92
|
+
protected override _root: NODE | undefined;
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* The function returns the root node of a tree or undefined if there is no root.
|
|
96
96
|
* @returns The root node of the tree structure, or undefined if there is no root node.
|
|
97
97
|
*/
|
|
98
|
-
get root(): NODE | undefined {
|
|
98
|
+
override get root(): NODE | undefined {
|
|
99
99
|
return this._root;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
protected _size: number = 0;
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* The function returns the size of an object.
|
|
106
|
-
* @returns The size of the object, which is a number.
|
|
107
|
-
*/
|
|
108
|
-
get size(): number {
|
|
109
|
-
return this._size;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
102
|
/**
|
|
113
103
|
* The function creates a new Red-Black Tree node with the specified key, value, and color.
|
|
114
104
|
* @param {K} key - The key parameter represents the key of the node being created. It is of type K,
|
|
@@ -208,7 +198,7 @@ export class RedBlackTree<
|
|
|
208
198
|
* @returns a boolean value.
|
|
209
199
|
*/
|
|
210
200
|
override isRealNode(node: NODE | undefined): node is NODE {
|
|
211
|
-
if (node === this.
|
|
201
|
+
if (node === this.SENTINEL || node === undefined) return false;
|
|
212
202
|
return node instanceof RedBlackTreeNode;
|
|
213
203
|
}
|
|
214
204
|
|
|
@@ -245,8 +235,7 @@ export class RedBlackTree<
|
|
|
245
235
|
iterationType = this.iterationType
|
|
246
236
|
): NODE | null | undefined {
|
|
247
237
|
if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
|
|
248
|
-
|
|
249
|
-
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
238
|
+
return super.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
250
239
|
}
|
|
251
240
|
|
|
252
241
|
/**
|
|
@@ -262,8 +251,8 @@ export class RedBlackTree<
|
|
|
262
251
|
* size counter to zero.
|
|
263
252
|
*/
|
|
264
253
|
override clear() {
|
|
254
|
+
super.clear();
|
|
265
255
|
this._root = this.SENTINEL;
|
|
266
|
-
this._size = 0;
|
|
267
256
|
}
|
|
268
257
|
|
|
269
258
|
/**
|
|
@@ -290,7 +279,7 @@ export class RedBlackTree<
|
|
|
290
279
|
|
|
291
280
|
const insertStatus = this._insert(newNode);
|
|
292
281
|
|
|
293
|
-
if (insertStatus ===
|
|
282
|
+
if (insertStatus === CRUD.CREATED) {
|
|
294
283
|
// Ensure the root is black
|
|
295
284
|
if (this.isRealNode(this._root)) {
|
|
296
285
|
this._root.color = RBTNColor.BLACK;
|
|
@@ -299,7 +288,7 @@ export class RedBlackTree<
|
|
|
299
288
|
}
|
|
300
289
|
this._size++;
|
|
301
290
|
return true;
|
|
302
|
-
} else return insertStatus ===
|
|
291
|
+
} else return insertStatus === CRUD.UPDATED;
|
|
303
292
|
}
|
|
304
293
|
|
|
305
294
|
/**
|
|
@@ -434,7 +423,7 @@ export class RedBlackTree<
|
|
|
434
423
|
* node in the tree.
|
|
435
424
|
* @returns {'inserted' | 'updated'} - The result of the insertion.
|
|
436
425
|
*/
|
|
437
|
-
protected _insert(node: NODE):
|
|
426
|
+
protected _insert(node: NODE): CRUD {
|
|
438
427
|
let current = this.root;
|
|
439
428
|
let parent: NODE | undefined = undefined;
|
|
440
429
|
|
|
@@ -446,7 +435,7 @@ export class RedBlackTree<
|
|
|
446
435
|
current = current.right ?? this.SENTINEL;
|
|
447
436
|
} else {
|
|
448
437
|
this._replaceNode(current, node);
|
|
449
|
-
return
|
|
438
|
+
return CRUD.UPDATED;
|
|
450
439
|
}
|
|
451
440
|
}
|
|
452
441
|
|
|
@@ -465,7 +454,7 @@ export class RedBlackTree<
|
|
|
465
454
|
node.color = RBTNColor.RED;
|
|
466
455
|
|
|
467
456
|
this._insertFixup(node);
|
|
468
|
-
return
|
|
457
|
+
return CRUD.CREATED;
|
|
469
458
|
}
|
|
470
459
|
|
|
471
460
|
/**
|
package/src/types/common.ts
CHANGED
|
@@ -63,3 +63,10 @@ export type BTNodePureExemplar<K, V, N> = [K, V | undefined] | BTNodePureKeyOrNo
|
|
|
63
63
|
export type BSTNKeyOrNode<K, N> = K | undefined | N;
|
|
64
64
|
|
|
65
65
|
export type BinaryTreeDeleteResult<N> = { deleted: N | null | undefined; needBalanced: N | null | undefined };
|
|
66
|
+
|
|
67
|
+
export enum CRUD {
|
|
68
|
+
CREATED = 'CREATED',
|
|
69
|
+
READ = 'READ',
|
|
70
|
+
UPDATED = 'UPDATED',
|
|
71
|
+
DELETED = 'DELETED'
|
|
72
|
+
}
|