From 56f1fabfca84128d8cc631b0fc744fc84a0f90d1 Mon Sep 17 00:00:00 2001 From: Revone Date: Mon, 15 Jan 2024 21:05:42 +0800 Subject: [PATCH] refactor: Renaming SENTINEL to NIL and placing the NIL node in the BinaryTree allows for direct equality checks in isNIL and isRealNode, avoiding excessive operations to improve performance. As a result, the performance of the get method in AVLTree has tripled. --- CHANGELOG.md | 2 +- README.md | 26 +++--- .../binary-tree/binary-tree.ts | 85 ++++++++++--------- src/data-structures/binary-tree/bst.ts | 37 +++++++- src/data-structures/binary-tree/rb-tree.ts | 78 ++--------------- .../binary-tree/avl-tree.test.ts | 4 + .../binary-tree/rb-tree.test.ts | 4 + .../binary-tree/overall.test.ts | 4 +- .../binary-tree/rb-tree.test.ts | 80 ++++++++--------- 9 files changed, 151 insertions(+), 169 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb0a83a..99a3b1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - [Semantic Versioning](https://semver.org/spec/v2.0.0.html) - [`auto-changelog`](https://github.com/CookPete/auto-changelog) -## [v1.51.0](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.51.1](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/README.md b/README.md index a379ff5..ba5bfd8 100644 --- a/README.md +++ b/README.md @@ -687,43 +687,43 @@ Version 11.7.9 [//]: # (No deletion!!! Start of Replace Section)
heap
-
test nametime taken (ms)executions per secsample deviation
100,000 add6.36157.241.88e-4
100,000 add & poll32.5630.720.01
+
test nametime taken (ms)executions per secsample deviation
100,000 add6.44155.391.89e-4
100,000 add & poll31.5431.717.91e-4
rb-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add55.4618.030.00
100,000 get114.638.720.00
100,000 iterator26.5237.710.01
100,000 add & delete orderly128.137.800.02
100,000 add & delete randomly228.894.370.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add55.6417.973.93e-4
100,000 add randomly70.3514.210.00
100,000 get115.518.660.00
100,000 iterator27.6436.180.01
100,000 add & delete orderly120.738.280.00
100,000 add & delete randomly223.374.480.00
queue
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push43.5322.970.01
100,000 push & shift4.80208.145.81e-4
Native JS Array 100,000 push & shift2201.640.450.11
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push42.8723.330.01
100,000 push & shift4.87205.176.94e-4
Native JS Array 100,000 push & shift2196.840.460.19
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push25.9138.590.01
1,000,000 push & pop30.7132.570.00
1,000,000 push & shift30.5932.690.00
100,000 push & shift3.23309.942.61e-4
Native JS Array 100,000 push & shift2525.120.400.39
100,000 unshift & shift2.87347.922.86e-4
Native JS Array 100,000 unshift & shift4400.380.230.14
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push23.6842.220.00
1,000,000 push & pop30.6832.600.00
1,000,000 push & shift30.4932.800.00
100,000 push & shift3.21311.512.41e-4
Native JS Array 100,000 push & shift2510.080.400.34
100,000 unshift & shift2.89346.572.98e-4
Native JS Array 100,000 unshift & shift4581.650.220.40
hash-map
-
test nametime taken (ms)executions per secsample deviation
1,000,000 set113.028.850.02
Native JS Map 1,000,000 set201.234.970.00
Native JS Set 1,000,000 add168.535.930.01
1,000,000 set & get118.498.440.02
Native JS Map 1,000,000 set & get263.493.800.01
Native JS Set 1,000,000 add & has168.285.940.01
1,000,000 ObjKey set & get309.883.230.01
Native JS Map 1,000,000 ObjKey set & get282.503.540.04
Native JS Set 1,000,000 ObjKey add & has268.423.730.03
+
test nametime taken (ms)executions per secsample deviation
1,000,000 set120.668.290.03
Native JS Map 1,000,000 set202.574.940.01
Native JS Set 1,000,000 add167.465.970.01
1,000,000 set & get115.608.650.01
Native JS Map 1,000,000 set & get265.343.770.01
Native JS Set 1,000,000 add & has167.855.960.01
1,000,000 ObjKey set & get308.733.240.03
Native JS Map 1,000,000 ObjKey set & get300.603.330.03
Native JS Set 1,000,000 ObjKey add & has270.493.700.04
trie
-
test nametime taken (ms)executions per secsample deviation
100,000 push44.8522.300.01
100,000 getWords84.8411.790.01
+
test nametime taken (ms)executions per secsample deviation
100,000 push45.7921.847.32e-4
100,000 getWords87.8511.380.00
avl-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add381.632.620.00
100,000 get354.692.820.00
100,000 iterator29.8733.480.01
100,000 add & delete orderly652.771.530.00
100,000 add & delete randomly929.071.080.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add260.783.830.00
100,000 add randomly306.613.260.00
100,000 get140.277.130.00
100,000 iterator29.9033.450.01
100,000 add & delete orderly428.762.330.00
100,000 add & delete randomly580.741.720.00
binary-tree-overall
-
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add5.55180.057.09e-5
10,000 RBTree add & delete randomly19.0652.461.94e-4
10,000 RBTree get0.611647.376.11e-6
10,000 AVLTree add32.0331.227.32e-4
10,000 AVLTree get19.6550.893.12e-4
10,000 AVLTree add & delete randomly62.0716.114.26e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add5.74174.109.29e-5
10,000 RBTree add & delete randomly18.8353.101.49e-4
10,000 RBTree get0.771290.557.33e-6
10,000 AVLTree add22.6044.252.14e-4
10,000 AVLTree get10.6394.081.02e-4
10,000 AVLTree add & delete randomly44.1722.643.52e-4
directed-graph
-
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109939.309.29e-7
1,000 addEdge6.15162.548.71e-4
1,000 getVertex0.052.18e+42.83e-7
1,000 getEdge23.9341.780.00
tarjan207.834.810.01
topologicalSort181.915.500.00
+
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.119501.691.02e-6
1,000 addEdge6.18161.814.27e-4
1,000 getVertex0.052.16e+43.23e-7
1,000 getEdge23.3142.900.00
tarjan206.064.850.01
topologicalSort181.655.510.01
doubly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push210.214.760.03
1,000,000 unshift218.634.570.05
1,000,000 unshift & shift162.146.170.01
1,000,000 addBefore319.753.130.06
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push207.884.810.04
1,000,000 unshift214.334.670.06
1,000,000 unshift & shift185.545.390.04
1,000,000 addBefore308.663.240.08
singly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift191.555.220.03
10,000 push & pop215.954.630.01
10,000 addBefore249.824.000.01
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift202.614.940.04
10,000 push & pop219.694.550.02
10,000 addBefore247.134.050.01
priority-queue
-
test nametime taken (ms)executions per secsample deviation
100,000 add27.5436.312.55e-4
100,000 add & poll75.8813.184.27e-4
+
test nametime taken (ms)executions per secsample deviation
100,000 add27.3636.559.92e-4
100,000 add & poll146.726.826.84e-4
stack
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push39.7825.140.01
1,000,000 push & pop46.9021.320.01
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push39.3625.410.01
1,000,000 push & pop47.8620.890.01
[//]: # (No deletion!!! End of Replace Section) diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index a111f74..85cb4e1 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -191,6 +191,16 @@ export class BinaryTree< return this._size; } + protected _NIL: NODE = new BinaryTreeNode(NaN as K) as unknown as NODE; + + /** + * The function returns the value of the _NIL property. + * @returns The method is returning the value of the `_NIL` property. + */ + get NIL(): NODE { + return this._NIL; + } + /** * Creates a new instance of BinaryTreeNode with the given key and value. * @param {K} key - The key for the new node. @@ -281,6 +291,15 @@ export class BinaryTree< } } + /** + * The function checks if a given node is a real node or null. + * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. + * @returns a boolean value. + */ + isNodeOrNull(node: KeyOrNodeOrEntry): node is NODE | null { + return this.isRealNode(node) || node === null; + } + /** * The function "isNode" checks if an keyOrNodeOrEntry is an instance of the BinaryTreeNode class. * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry`. @@ -290,6 +309,26 @@ export class BinaryTree< return keyOrNodeOrEntry instanceof BinaryTreeNode; } + /** + * The function checks if a given node is a real node by verifying if it is an instance of + * BinaryTreeNode and its key is not NaN. + * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. + * @returns a boolean value. + */ + isRealNode(node: KeyOrNodeOrEntry): node is NODE { + if (!this.isNode(node)) return false; + return node !== this.NIL; + } + + /** + * The function checks if a given node is a BinaryTreeNode instance and has a key value of NaN. + * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. + * @returns a boolean value. + */ + isNIL(node: KeyOrNodeOrEntry) { + return node === this.NIL; + } + /** * The function checks if a given value is an entry in a binary tree node. * @param keyOrNodeOrEntry - KeyOrNodeOrEntry - A generic type representing a node in a binary tree. It has @@ -300,34 +339,6 @@ export class BinaryTree< return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2; } - /** - * The function checks if a given node is a real node by verifying if it is an instance of - * BinaryTreeNode and its key is not NaN. - * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. - * @returns a boolean value. - */ - isRealNode(node: KeyOrNodeOrEntry): node is NODE { - return node instanceof BinaryTreeNode && String(node.key) !== 'NaN'; - } - - /** - * The function checks if a given node is a BinaryTreeNode instance and has a key value of NaN. - * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. - * @returns a boolean value. - */ - isNIL(node: KeyOrNodeOrEntry) { - return node instanceof BinaryTreeNode && String(node.key) === 'NaN'; - } - - /** - * The function checks if a given node is a real node or null. - * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type. - * @returns a boolean value. - */ - isNodeOrNull(node: KeyOrNodeOrEntry): node is NODE | null { - return this.isRealNode(node) || node === null; - } - /** * Time Complexity O(n) * Space Complexity O(1) @@ -612,9 +623,9 @@ export class BinaryTree< ans.push(cur); if (onlyOne) return; } - if (!cur.left && !cur.right) return; - cur.left && dfs(cur.left); - cur.right && dfs(cur.right); + if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; + this.isRealNode(cur.left) && dfs(cur.left); + this.isRealNode(cur.right) && dfs(cur.right); }; dfs(beginRoot); @@ -622,13 +633,13 @@ export class BinaryTree< const stack = [beginRoot]; while (stack.length > 0) { const cur = stack.pop(); - if (cur) { + if (this.isRealNode(cur)) { if (callback(cur) === identifier) { ans.push(cur); if (onlyOne) return ans; } - cur.left && stack.push(cur.left); - cur.right && stack.push(cur.right); + this.isRealNode(cur.left) && stack.push(cur.left); + this.isRealNode(cur.right) && stack.push(cur.right); } } } @@ -689,9 +700,6 @@ export class BinaryTree< beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): NODE | null | undefined { - if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) - callback = (node => node) as C; - return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null; } @@ -793,9 +801,6 @@ export class BinaryTree< beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): V | undefined { - if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) - callback = (node => node) as C; - return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined; } diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index cee0877..1368f4f 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -13,7 +13,7 @@ import type { BTNodePureExemplar, KeyOrNodeOrEntry } from '../../types'; -import { BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types'; +import { BSTNKeyOrNode, BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types'; import { BinaryTree, BinaryTreeNode } from './binary-tree'; import { IBinaryTree } from '../../interfaces'; import { Queue } from '../queue'; @@ -543,6 +543,41 @@ export class BST< return ans; } + /** + * Time Complexity: O(log n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(log n) + * Space Complexity: O(1) + * + * The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and + * callback function. + * @param {ReturnType | undefined} identifier - The `identifier` parameter is the value or key + * that you want to search for in the binary search tree. It can be of any type that is compatible + * with the type of nodes in the tree. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the tree. It is used to determine whether a node matches the given identifier. The `callback` + * function should take a node as its parameter and return a value that can be compared to the + * `identifier` parameter. + * @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary + * search tree. It can be either a key or a node. If it is a key, it will be converted to a node + * using the `ensureNode` method. If it is not provided, the `root` + * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + * be performed when searching for nodes in the binary search tree. It is an optional parameter and + * its default value is taken from the `iterationType` property of the class. + * @returns The method is returning a value of type `NODE | null | undefined`. + */ + override getNode>( + identifier: ReturnType | undefined, + callback: C = this._DEFAULT_CALLBACK as C, + beginRoot: BSTNKeyOrNode = this.root, + iterationType: IterationType = this.iterationType + ): NODE | undefined { + return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined; + } + /** * Time complexity: O(n) * Space complexity: O(n) diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 1e48309..b30777b 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -1,8 +1,6 @@ import type { BinaryTreeDeleteResult, - BSTNKeyOrNode, BTNCallback, - IterationType, KeyOrNodeOrEntry, RBTreeOptions, RedBlackTreeNested, @@ -73,23 +71,13 @@ export class RedBlackTree< constructor(keysOrNodesOrEntries: Iterable> = [], options?: RBTreeOptions) { super([], options); - this._root = this.SENTINEL; + this._root = this.NIL; if (keysOrNodesOrEntries) { this.addMany(keysOrNodesOrEntries); } } - protected _SENTINEL: NODE = new RedBlackTreeNode(NaN as K) as unknown as NODE; - - /** - * The function returns the value of the _SENTINEL property. - * @returns The method is returning the value of the `_SENTINEL` property. - */ - get SENTINEL(): NODE { - return this._SENTINEL; - } - protected override _root: NODE | undefined; /** @@ -184,60 +172,6 @@ export class RedBlackTree< return keyOrNodeOrEntry instanceof RedBlackTreeNode; } - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(1) - * Space Complexity: O(1) - * - * The function checks if a given node is a real node in a Red-Black Tree. - * @param {NODE | undefined} node - The `node` parameter is of type `NODE | undefined`, which means - * it can either be of type `NODE` or `undefined`. - * @returns a boolean value. - */ - override isRealNode(node: NODE | undefined): node is NODE { - if (node === this.SENTINEL || node === undefined) return false; - return node instanceof RedBlackTreeNode; - } - - /** - * Time Complexity: O(log n) - * Space Complexity: O(1) - */ - - /** - * Time Complexity: O(log n) - * Space Complexity: O(1) - * - * The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and - * callback function. - * @param {ReturnType | undefined} identifier - The `identifier` parameter is the value or key - * that you want to search for in the binary search tree. It can be of any type that is compatible - * with the type of nodes in the tree. - * @param {C} callback - The `callback` parameter is a function that will be called for each node in - * the tree. It is used to determine whether a node matches the given identifier. The `callback` - * function should take a node as its parameter and return a value that can be compared to the - * `identifier` parameter. - * @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary - * search tree. It can be either a key or a node. If it is a key, it will be converted to a node - * using the `ensureNode` method. If it is not provided, the `root` - * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to - * be performed when searching for nodes in the binary search tree. It is an optional parameter and - * its default value is taken from the `iterationType` property of the class. - * @returns The method is returning a value of type `NODE | null | undefined`. - */ - override getNode>( - identifier: ReturnType | undefined, - callback: C = this._DEFAULT_CALLBACK as C, - beginRoot: BSTNKeyOrNode = this.root, - iterationType: IterationType = this.iterationType - ): NODE | null | undefined { - return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined; - } - /** * Time Complexity: O(1) * Space Complexity: O(1) @@ -252,7 +186,7 @@ export class RedBlackTree< */ override clear() { super.clear(); - this._root = this.SENTINEL; + this._root = this.NIL; } /** @@ -430,9 +364,9 @@ export class RedBlackTree< while (this.isRealNode(current)) { parent = current; if (node.key < current.key) { - current = current.left ?? this.SENTINEL; + current = current.left ?? this.NIL; } else if (node.key > current.key) { - current = current.right ?? this.SENTINEL; + current = current.right ?? this.NIL; } else { this._replaceNode(current, node); return 'UPDATED'; @@ -449,8 +383,8 @@ export class RedBlackTree< parent.right = node; } - node.left = this.SENTINEL; - node.right = this.SENTINEL; + node.left = this.NIL; + node.right = this.NIL; node.color = 'RED'; this._insertFixup(node); diff --git a/test/performance/data-structures/binary-tree/avl-tree.test.ts b/test/performance/data-structures/binary-tree/avl-tree.test.ts index 3885c1b..1fb736f 100644 --- a/test/performance/data-structures/binary-tree/avl-tree.test.ts +++ b/test/performance/data-structures/binary-tree/avl-tree.test.ts @@ -12,6 +12,10 @@ suite avlTree.clear(); for (let i = 0; i < randomArray.length; i++) avlTree.add(i); }) + .add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => { + avlTree.clear(); + for (let i = 0; i < randomArray.length; i++) avlTree.add(randomArray[i]); + }) .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => { for (let i = 0; i < randomArray.length; i++) avlTree.get(randomArray[i]); }) diff --git a/test/performance/data-structures/binary-tree/rb-tree.test.ts b/test/performance/data-structures/binary-tree/rb-tree.test.ts index 298c0ca..6f8f823 100644 --- a/test/performance/data-structures/binary-tree/rb-tree.test.ts +++ b/test/performance/data-structures/binary-tree/rb-tree.test.ts @@ -15,6 +15,10 @@ suite rbTree.clear(); for (let i = 0; i < randomArray.length; i++) rbTree.add(i); }) + .add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => { + rbTree.clear(); + for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]); + }) .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => { for (let i = 0; i < randomArray.length; i++) rbTree.get(randomArray[i]); }) diff --git a/test/unit/data-structures/binary-tree/overall.test.ts b/test/unit/data-structures/binary-tree/overall.test.ts index 68ad2c6..f83394c 100644 --- a/test/unit/data-structures/binary-tree/overall.test.ts +++ b/test/unit/data-structures/binary-tree/overall.test.ts @@ -20,8 +20,8 @@ describe('Overall BinaryTree Test', () => { leftMost?.key === 1; // true expect(leftMost?.key).toBe(1); bst.delete(6); - bst.getNode(6); // null - expect(bst.getNode(6)).toBeNull(); + bst.getNode(6); // undefined + expect(bst.getNode(6)).toBe(undefined); bst.isAVLBalanced(); // true or false expect(bst.isAVLBalanced()).toBe(true); const bfsIDs: number[] = []; diff --git a/test/unit/data-structures/binary-tree/rb-tree.test.ts b/test/unit/data-structures/binary-tree/rb-tree.test.ts index f58e8e7..a5a8760 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -74,7 +74,7 @@ describe('RedBlackTree 1', () => { it('should handle an empty rbTree', () => { const minNode = rbTree.getLeftMost(rbTree.root); - expect(minNode).toBe(rbTree.SENTINEL); + expect(minNode).toBe(rbTree.NIL); }); }); @@ -92,7 +92,7 @@ describe('RedBlackTree 1', () => { it('should handle an empty rbTree', () => { const maxNode = rbTree.getRightMost(rbTree.root); - expect(maxNode).toBe(rbTree.SENTINEL); + expect(maxNode).toBe(rbTree.NIL); }); }); @@ -116,7 +116,7 @@ describe('RedBlackTree 1', () => { const node = rbTree.getNode(10); const successorNode = rbTree.getSuccessor(node!); - // TODO not sure if it should be undefined or rbTree.SENTINEL + // TODO not sure if it should be undefined or rbTree.NIL expect(successorNode).toBe(undefined); }); }); @@ -141,7 +141,7 @@ describe('RedBlackTree 1', () => { const node = rbTree.getNode(20); const predecessorNode = rbTree.getPredecessor(node!); - // TODO not sure if it should be rbTree.SENTINEL or something else. + // TODO not sure if it should be rbTree.NIL or something else. expect(predecessorNode).toBe(rbTree.getNode(20)); }); }); @@ -279,28 +279,28 @@ describe('RedBlackTree 2', () => { expect(node5F?.parent).toBe(node10F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node20F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe('RED'); - expect(node21F?.left).toBe(rbTree.SENTINEL); - expect(node21F?.right).toBe(rbTree.SENTINEL); + expect(node21F?.left).toBe(rbTree.NIL); + expect(node21F?.right).toBe(rbTree.NIL); expect(node21F?.parent).toBe(node20F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe('RED'); - expect(node6F?.left).toBe(rbTree.SENTINEL); - expect(node6F?.right).toBe(rbTree.SENTINEL); + expect(node6F?.left).toBe(rbTree.NIL); + expect(node6F?.right).toBe(rbTree.NIL); expect(node6F?.parent).toBe(node5F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe('RED'); - expect(node2F?.left).toBe(rbTree.SENTINEL); - expect(node2F?.right).toBe(rbTree.SENTINEL); + expect(node2F?.left).toBe(rbTree.NIL); + expect(node2F?.right).toBe(rbTree.NIL); expect(node2F?.parent).toBe(node5F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node20F); rbTree.delete(5); node10F = rbTree.getNode(10); @@ -323,28 +323,28 @@ describe('RedBlackTree 2', () => { expect(node5F).toBe(undefined); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node20F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe('RED'); - expect(node21F?.left).toBe(rbTree.SENTINEL); - expect(node21F?.right).toBe(rbTree.SENTINEL); + expect(node21F?.left).toBe(rbTree.NIL); + expect(node21F?.right).toBe(rbTree.NIL); expect(node21F?.parent).toBe(node20F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe('BLACK'); expect(node6F?.left).toBe(node2F); - expect(node6F?.right).toBe(rbTree.SENTINEL); + expect(node6F?.right).toBe(rbTree.NIL); expect(node6F?.parent).toBe(node10F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe('RED'); - expect(node2F?.left).toBe(rbTree.SENTINEL); - expect(node2F?.right).toBe(rbTree.SENTINEL); + expect(node2F?.left).toBe(rbTree.NIL); + expect(node2F?.right).toBe(rbTree.NIL); expect(node2F?.parent).toBe(node6F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node20F); rbTree.delete(20); node10F = rbTree.getNode(10); @@ -363,28 +363,28 @@ describe('RedBlackTree 2', () => { expect(node5F).toBe(undefined); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node21F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe('BLACK'); expect(node21F?.left).toBe(node15F); - expect(node21F?.right).toBe(rbTree.SENTINEL); + expect(node21F?.right).toBe(rbTree.NIL); expect(node21F?.parent).toBe(node10F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe('BLACK'); expect(node6F?.left).toBe(node2F); - expect(node6F?.right).toBe(rbTree.SENTINEL); + expect(node6F?.right).toBe(rbTree.NIL); expect(node6F?.parent).toBe(node10F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe('RED'); - expect(node2F?.left).toBe(rbTree.SENTINEL); - expect(node2F?.right).toBe(rbTree.SENTINEL); + expect(node2F?.left).toBe(rbTree.NIL); + expect(node2F?.right).toBe(rbTree.NIL); expect(node2F?.parent).toBe(node6F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe('RED'); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(node21F); }); @@ -394,8 +394,8 @@ describe('RedBlackTree 2', () => { rbTree.add(5); rbTree.add(15); const node15F = rbTree.getNode(15); - expect(node15F?.left).toBe(rbTree.SENTINEL); - expect(node15F?.right).toBe(rbTree.SENTINEL); + expect(node15F?.left).toBe(rbTree.NIL); + expect(node15F?.right).toBe(rbTree.NIL); expect(node15F?.parent).toBe(rbTree.getNode(5)); rbTree.add(25); @@ -410,8 +410,8 @@ describe('RedBlackTree 2', () => { rbTree.add(155); rbTree.add(225); const node225F = rbTree.getNode(225); - expect(node225F?.left).toBe(rbTree.SENTINEL); - expect(node225F?.right).toBe(rbTree.SENTINEL); + expect(node225F?.left).toBe(rbTree.NIL); + expect(node225F?.right).toBe(rbTree.NIL); expect(node225F?.parent?.key).toBe(155); rbTree.add(7); isDebug && rbTree.print(); @@ -438,14 +438,14 @@ describe('RedBlackTree 2', () => { const node50 = rbTree.getNode(50); expect(node50?.key).toBe(50); expect(node50?.left?.key).toBe(33); - expect(node50?.right).toBe(rbTree.SENTINEL); + expect(node50?.right).toBe(rbTree.NIL); const node15Fo = rbTree.getNode(15); expect(node15Fo?.key).toBe(15); - expect(node15Fo?.left).toBe(rbTree.SENTINEL); + expect(node15Fo?.left).toBe(rbTree.NIL); const node225S = rbTree.getNode(225); - expect(node225S?.left).toBe(rbTree.SENTINEL); - expect(node225S?.right).toBe(rbTree.SENTINEL); + expect(node225S?.left).toBe(rbTree.NIL); + expect(node225S?.right).toBe(rbTree.NIL); expect(node225S?.parent?.key).toBe(155); // TODO // expect(rbTree.getNode(0)).toBe(undefined); @@ -512,7 +512,7 @@ describe('RedBlackTree 2', () => { rbTree.delete(getRandomInt(-100, 1000)); } - // TODO there is a bug when dfs the rbTree with SENTINEL node + // TODO there is a bug when dfs the rbTree with NIL node // expect(rbTree.isBST()).toBe(true); }); const { HUNDRED_THOUSAND } = magnitude;