From a653d465fa9ddef7e28a6d1414529e7a5930fae2 Mon Sep 17 00:00:00 2001 From: Revone Date: Fri, 12 Jan 2024 14:15:05 +0800 Subject: [PATCH] Refactor: Use 'this.isRealNode' instead of explicit null checks in getHeight, getMinHeight, and getNodeByKey methods in the binary tree. In the red-black tree, directly invoke the parent class getNode method, significantly improving the speed of red-black tree node deletion and retrieval. --- .../binary-tree/binary-tree.ts | 20 +- src/data-structures/binary-tree/bst.ts | 34 +- src/data-structures/binary-tree/rb-tree.ts | 3 +- .../binary-tree/avl-tree-multi-map.test.ts | 2 +- .../binary-tree/rb-tree.test.ts | 514 +++++++++--------- .../binary-tree/tree-multi-map.test.ts | 482 ++++++++-------- 6 files changed, 534 insertions(+), 521 deletions(-) diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index f6fa66b..986127b 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -1021,7 +1021,7 @@ export class BinaryTree< */ getHeight(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): number { beginRoot = this.ensureNode(beginRoot); - if (!beginRoot) return -1; + if (!this.isRealNode(beginRoot)) return -1; if (iterationType === IterationType.RECURSIVE) { const _getMaxHeight = (cur: NODE | null | undefined): number => { @@ -1073,8 +1073,8 @@ export class BinaryTree< if (iterationType === IterationType.RECURSIVE) { const _getMinHeight = (cur: NODE | null | undefined): number => { - if (!cur) return 0; - if (!cur.left && !cur.right) return 0; + if (!this.isRealNode(cur)) return 0; + if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0; const leftMinHeight = _getMinHeight(cur.left); const rightMinHeight = _getMinHeight(cur.right); return Math.min(leftMinHeight, rightMinHeight) + 1; @@ -1088,16 +1088,16 @@ export class BinaryTree< const depths: Map = new Map(); while (stack.length > 0 || node) { - if (node) { + if (this.isRealNode(node)) { stack.push(node); node = node.left; } else { node = stack[stack.length - 1]; - if (!node.right || last === node.right) { + if (!this.isRealNode(node.right) || last === node.right) { node = stack.pop(); - if (node) { - const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1; - const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1; + if (this.isRealNode(node)) { + const leftMinHeight = this.isRealNode(node.left) ? depths.get(node.left) ?? -1 : -1; + const rightMinHeight = this.isRealNode(node.right) ? depths.get(node.right) ?? -1 : -1; depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight)); last = node; node = null; @@ -1169,9 +1169,10 @@ export class BinaryTree< beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType ): NODE | null | undefined { + if (this.isNIL(beginRoot)) return beginRoot as NODE; beginRoot = this.ensureNode(beginRoot); - if (!beginRoot) return beginRoot; + if (!this.isRealNode(beginRoot)) return beginRoot; if (iterationType === IterationType.RECURSIVE) { const _traverse = (cur: NODE): NODE => { @@ -1215,6 +1216,7 @@ export class BinaryTree< beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType ): NODE | null | undefined { + if (this.isNIL(beginRoot)) return beginRoot as NODE; // TODO support get right most by passing key in beginRoot = this.ensureNode(beginRoot); if (!beginRoot) return beginRoot; diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 73448b2..1da74b4 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -426,14 +426,14 @@ export class BST< * found in the binary tree. If no node is found, it returns `undefined`. */ override getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined { - if (!this.root) return undefined; + if (!this.isRealNode(this.root)) return undefined; if (iterationType === IterationType.RECURSIVE) { const _dfs = (cur: NODE): NODE | undefined => { if (cur.key === key) return cur; - if (!cur.left && !cur.right) return; + if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; - if (this._compare(cur.key, key) === CP.gt && cur.left) return _dfs(cur.left); - if (this._compare(cur.key, key) === CP.lt && cur.right) return _dfs(cur.right); + if (this._compare(cur.key, key) === CP.gt && this.isRealNode(cur.left)) return _dfs(cur.left); + if (this._compare(cur.key, key) === CP.lt && this.isRealNode(cur.right)) return _dfs(cur.right); }; return _dfs(this.root); @@ -441,10 +441,10 @@ export class BST< const queue = new Queue([this.root]); while (queue.size > 0) { const cur = queue.shift(); - if (cur) { + if (this.isRealNode(cur)) { if (this._compare(cur.key, key) === CP.eq) return cur; - if (this._compare(cur.key, key) === CP.gt) cur.left && queue.push(cur.left); - if (this._compare(cur.key, key) === CP.lt) cur.right && queue.push(cur.right); + if (this._compare(cur.key, key) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left); + if (this._compare(cur.key, key) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right); } } } @@ -497,14 +497,14 @@ export class BST< if (onlyOne) return; } - if (!cur.left && !cur.right) return; + if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; // TODO potential bug if (callback === this._defaultOneParamCallback) { - if (this._compare(cur.key, identifier as K) === CP.gt) cur.left && _traverse(cur.left); - if (this._compare(cur.key, identifier as K) === CP.lt) cur.right && _traverse(cur.right); + if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && _traverse(cur.left); + if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && _traverse(cur.right); } else { - cur.left && _traverse(cur.left); - cur.right && _traverse(cur.right); + this.isRealNode(cur.left) && _traverse(cur.left); + this.isRealNode(cur.right) && _traverse(cur.right); } }; @@ -513,7 +513,7 @@ export class BST< const queue = new Queue([beginRoot]); while (queue.size > 0) { const cur = queue.shift(); - if (cur) { + if (this.isRealNode(cur)) { const callbackResult = callback(cur); if (callbackResult === identifier) { ans.push(cur); @@ -521,11 +521,11 @@ export class BST< } // TODO potential bug if (callback === this._defaultOneParamCallback) { - if (this._compare(cur.key, identifier as K) === CP.gt) cur.left && queue.push(cur.left); - if (this._compare(cur.key, identifier as K) === CP.lt) cur.right && queue.push(cur.right); + if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left); + if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right); } else { - cur.left && queue.push(cur.left); - cur.right && queue.push(cur.right); + this.isRealNode(cur.left) && queue.push(cur.left); + this.isRealNode(cur.right) && queue.push(cur.right); } } } diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 479193a..50269f3 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -235,8 +235,7 @@ export class RedBlackTree< iterationType = this.iterationType ): NODE | null | undefined { if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C; - beginRoot = this.ensureNode(beginRoot); - return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined; + return super.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined; } /** diff --git a/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts b/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts index ec3165f..877737d 100644 --- a/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +++ b/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts @@ -35,7 +35,7 @@ describe('AVLTreeMultiMap count', () => { [2, 2], [3, 3] ]); - tm.add([2, 2], undefined, 10) + tm.add([2, 2], undefined, 10); tm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1); tm.delete(2); expect(tm.count).toBe(12); 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 5857213..759a298 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -8,136 +8,136 @@ const isDebug = isDebugTest; // const isDebug = true; describe('RedBlackTree 1', () => { - let tree: RedBlackTree; + let rbTree: RedBlackTree; beforeEach(() => { - tree = new RedBlackTree(); + rbTree = new RedBlackTree(); }); describe('add and getNode', () => { - it('should add and find a node in the tree', () => { - tree.add(10); - tree.add(20); - tree.add(5); + it('should add and find a node in the rbTree', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); - expect(tree.getNode(10)).toBeInstanceOf(RedBlackTreeNode); - expect(tree.getNode(20)).toBeInstanceOf(RedBlackTreeNode); - expect(tree.getNode(5)).toBeInstanceOf(RedBlackTreeNode); - expect(tree.getNode(15)).toBe(undefined); + expect(rbTree.getNode(10)).toBeInstanceOf(RedBlackTreeNode); + expect(rbTree.getNode(20)).toBeInstanceOf(RedBlackTreeNode); + expect(rbTree.getNode(5)).toBeInstanceOf(RedBlackTreeNode); + expect(rbTree.getNode(15)).toBe(undefined); }); it('should add and find nodes with negative keys', () => { - tree.add(-10); - tree.add(-20); + rbTree.add(-10); + rbTree.add(-20); - expect(tree.getNode(-10)).toBeInstanceOf(RedBlackTreeNode); - expect(tree.getNode(-20)).toBeInstanceOf(RedBlackTreeNode); + expect(rbTree.getNode(-10)).toBeInstanceOf(RedBlackTreeNode); + expect(rbTree.getNode(-20)).toBeInstanceOf(RedBlackTreeNode); }); }); describe('deleteNode', () => { - it('should delete a node from the tree', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.delete(20); + it('should delete a node from the rbTree', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.delete(20); - expect(tree.getNode(20)).toBe(undefined); + expect(rbTree.getNode(20)).toBe(undefined); }); it('should handle deleting a non-existent node', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.delete(15); + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.delete(15); - expect(tree.getNode(15)).toBe(undefined); + expect(rbTree.getNode(15)).toBe(undefined); }); }); describe('minimum', () => { - it('should find the minimum node in the tree', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(3); + it('should find the minimum node in the rbTree', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.add(15); + rbTree.add(3); - const minNode = tree.getLeftMost(tree.root); + const minNode = rbTree.getLeftMost(rbTree.root); expect(minNode?.key).toBe(3); }); - it('should handle an empty tree', () => { - const minNode = tree.getLeftMost(tree.root); - expect(minNode).toBe(tree.SENTINEL); + it('should handle an empty rbTree', () => { + const minNode = rbTree.getLeftMost(rbTree.root); + expect(minNode).toBe(rbTree.SENTINEL); }); }); describe('getRightMost', () => { - it('should find the getRightMost node in the tree', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(25); + it('should find the getRightMost node in the rbTree', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.add(15); + rbTree.add(25); - const maxNode = tree.getRightMost(tree.root); + const maxNode = rbTree.getRightMost(rbTree.root); expect(maxNode?.key).toBe(25); }); - it('should handle an empty tree', () => { - const maxNode = tree.getRightMost(tree.root); - expect(maxNode).toBe(tree.SENTINEL); + it('should handle an empty rbTree', () => { + const maxNode = rbTree.getRightMost(rbTree.root); + expect(maxNode).toBe(rbTree.SENTINEL); }); }); describe('getSuccessor', () => { it('should find the getSuccessor of a node', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(25); + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.add(15); + rbTree.add(25); - const node = tree.getNode(15); - const successorNode = tree.getSuccessor(node!); + const node = rbTree.getNode(15); + const successorNode = rbTree.getSuccessor(node!); expect(successorNode?.key).toBe(20); }); it('should handle a node with no getSuccessor', () => { - tree.add(10); - tree.add(5); + rbTree.add(10); + rbTree.add(5); - const node = tree.getNode(10); - const successorNode = tree.getSuccessor(node!); - // TODO not sure if it should be undefined or tree.SENTINEL + const node = rbTree.getNode(10); + const successorNode = rbTree.getSuccessor(node!); + // TODO not sure if it should be undefined or rbTree.SENTINEL expect(successorNode).toBe(undefined); }); }); describe('getPredecessor', () => { it('should find the getPredecessor of a node', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(25); + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.add(15); + rbTree.add(25); - const node = tree.getNode(20); - const predecessorNode = tree.getPredecessor(node!); + const node = rbTree.getNode(20); + const predecessorNode = rbTree.getPredecessor(node!); expect(predecessorNode?.key).toBe(15); }); it('should handle a node with no getPredecessor', () => { - tree.add(10); - tree.add(20); + rbTree.add(10); + rbTree.add(20); - const node = tree.getNode(20); - const predecessorNode = tree.getPredecessor(node!); - // TODO not sure if it should be tree.SENTINEL or something else. - expect(predecessorNode).toBe(tree.getNode(20)); + const node = rbTree.getNode(20); + const predecessorNode = rbTree.getPredecessor(node!); + // TODO not sure if it should be rbTree.SENTINEL or something else. + expect(predecessorNode).toBe(rbTree.getNode(20)); }); }); @@ -180,83 +180,83 @@ describe('RedBlackTree 1', () => { }); describe('RedBlackTree 2', () => { - let tree: RedBlackTree; + let rbTree: RedBlackTree; beforeEach(() => { - tree = new RedBlackTree(); + rbTree = new RedBlackTree(); }); - it('should add nodes into the tree', () => { - tree.add(10); - expect(tree.getNode(10)).toBeDefined(); - tree.add(20); - expect(tree.getNode(20)).toBeDefined(); - tree.add(5); - expect(tree.getNode(5)).toBeDefined(); + it('should add nodes into the rbTree', () => { + rbTree.add(10); + expect(rbTree.getNode(10)).toBeDefined(); + rbTree.add(20); + expect(rbTree.getNode(20)).toBeDefined(); + rbTree.add(5); + expect(rbTree.getNode(5)).toBeDefined(); }); - it('should delete nodes from the tree', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.delete(20); - expect(tree.getNode(20)).toBe(undefined); + it('should delete nodes from the rbTree', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.delete(20); + expect(rbTree.getNode(20)).toBe(undefined); }); it('should get the successor of a node', () => { - tree.add(10); - tree.add(20); - const node = tree.getNode(10); - const successor = tree.getSuccessor(node!); + rbTree.add(10); + rbTree.add(20); + const node = rbTree.getNode(10); + const successor = rbTree.getSuccessor(node!); expect(successor?.key).toBe(20); }); it('should get the predecessor of a node', () => { - tree.add(10); - tree.add(20); - const node = tree.getNode(20); - const predecessor = tree.getPredecessor(node!); + rbTree.add(10); + rbTree.add(20); + const node = rbTree.getNode(20); + const predecessor = rbTree.getPredecessor(node!); expect(predecessor?.key).toBe(20); }); it('should rotate nodes to the left', () => { - tree.add(10); - tree.add(20); - tree.add(5); - const node = tree.getNode(10); - tree.add(15); + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + const node = rbTree.getNode(10); + rbTree.add(15); // Verify that rotation has occurred expect(node?.left?.key).toBe(5); expect(node?.right?.key).toBe(20); }); it('should rotate nodes to the right', () => { - tree.add(10); - tree.add(20); - tree.add(5); - const node = tree.getNode(20); - tree.add(25); + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + const node = rbTree.getNode(20); + rbTree.add(25); // Verify that rotation has occurred expect(node?.left?.key).toBeNaN(); expect(node?.right?.key).toBe(25); }); - it('should all node attributes fully conform to the red-black tree standards.', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(21); - tree.add(6); - tree.add(2); + it('should all node attributes fully conform to the red-black rbTree standards.', () => { + rbTree.add(10); + rbTree.add(20); + rbTree.add(5); + rbTree.add(15); + rbTree.add(21); + rbTree.add(6); + rbTree.add(2); - let node10F = tree.getNode(10); - let node20F = tree.getNode(20); - let node5F = tree.getNode(5); - let node15F = tree.getNode(15); - let node21F = tree.getNode(21); - let node6F = tree.getNode(6); - let node2F = tree.getNode(2); + let node10F = rbTree.getNode(10); + let node20F = rbTree.getNode(20); + let node5F = rbTree.getNode(5); + let node15F = rbTree.getNode(15); + let node21F = rbTree.getNode(21); + let node6F = rbTree.getNode(6); + let node2F = rbTree.getNode(2); expect(node10F?.key).toBe(10); expect(node10F?.color).toBe(RBTNColor.BLACK); expect(node10F?.left).toBe(node5F); @@ -274,37 +274,37 @@ describe('RedBlackTree 2', () => { expect(node5F?.parent).toBe(node10F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node20F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe(RBTNColor.RED); - expect(node21F?.left).toBe(tree.SENTINEL); - expect(node21F?.right).toBe(tree.SENTINEL); + expect(node21F?.left).toBe(rbTree.SENTINEL); + expect(node21F?.right).toBe(rbTree.SENTINEL); expect(node21F?.parent).toBe(node20F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe(RBTNColor.RED); - expect(node6F?.left).toBe(tree.SENTINEL); - expect(node6F?.right).toBe(tree.SENTINEL); + expect(node6F?.left).toBe(rbTree.SENTINEL); + expect(node6F?.right).toBe(rbTree.SENTINEL); expect(node6F?.parent).toBe(node5F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe(RBTNColor.RED); - expect(node2F?.left).toBe(tree.SENTINEL); - expect(node2F?.right).toBe(tree.SENTINEL); + expect(node2F?.left).toBe(rbTree.SENTINEL); + expect(node2F?.right).toBe(rbTree.SENTINEL); expect(node2F?.parent).toBe(node5F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node20F); - tree.delete(5); - node10F = tree.getNode(10); - node20F = tree.getNode(20); - node5F = tree.getNode(5); - node15F = tree.getNode(15); - node21F = tree.getNode(21); - node6F = tree.getNode(6); - node2F = tree.getNode(2); + rbTree.delete(5); + node10F = rbTree.getNode(10); + node20F = rbTree.getNode(20); + node5F = rbTree.getNode(5); + node15F = rbTree.getNode(15); + node21F = rbTree.getNode(21); + node6F = rbTree.getNode(6); + node2F = rbTree.getNode(2); expect(node10F?.key).toBe(10); expect(node10F?.color).toBe(RBTNColor.BLACK); expect(node10F?.left).toBe(node6F); @@ -318,37 +318,37 @@ describe('RedBlackTree 2', () => { expect(node5F).toBe(undefined); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node20F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe(RBTNColor.RED); - expect(node21F?.left).toBe(tree.SENTINEL); - expect(node21F?.right).toBe(tree.SENTINEL); + expect(node21F?.left).toBe(rbTree.SENTINEL); + expect(node21F?.right).toBe(rbTree.SENTINEL); expect(node21F?.parent).toBe(node20F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe(RBTNColor.BLACK); expect(node6F?.left).toBe(node2F); - expect(node6F?.right).toBe(tree.SENTINEL); + expect(node6F?.right).toBe(rbTree.SENTINEL); expect(node6F?.parent).toBe(node10F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe(RBTNColor.RED); - expect(node2F?.left).toBe(tree.SENTINEL); - expect(node2F?.right).toBe(tree.SENTINEL); + expect(node2F?.left).toBe(rbTree.SENTINEL); + expect(node2F?.right).toBe(rbTree.SENTINEL); expect(node2F?.parent).toBe(node6F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node20F); - tree.delete(20); - node10F = tree.getNode(10); - node20F = tree.getNode(20); - node5F = tree.getNode(5); - node15F = tree.getNode(15); - node21F = tree.getNode(21); - node6F = tree.getNode(6); - node2F = tree.getNode(2); + rbTree.delete(20); + node10F = rbTree.getNode(10); + node20F = rbTree.getNode(20); + node5F = rbTree.getNode(5); + node15F = rbTree.getNode(15); + node21F = rbTree.getNode(21); + node6F = rbTree.getNode(6); + node2F = rbTree.getNode(2); expect(node10F?.key).toBe(10); expect(node10F?.color).toBe(RBTNColor.BLACK); expect(node10F?.left).toBe(node6F); @@ -358,167 +358,167 @@ describe('RedBlackTree 2', () => { expect(node5F).toBe(undefined); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node21F); expect(node21F?.key).toBe(21); expect(node21F?.color).toBe(RBTNColor.BLACK); expect(node21F?.left).toBe(node15F); - expect(node21F?.right).toBe(tree.SENTINEL); + expect(node21F?.right).toBe(rbTree.SENTINEL); expect(node21F?.parent).toBe(node10F); expect(node6F?.key).toBe(6); expect(node6F?.color).toBe(RBTNColor.BLACK); expect(node6F?.left).toBe(node2F); - expect(node6F?.right).toBe(tree.SENTINEL); + expect(node6F?.right).toBe(rbTree.SENTINEL); expect(node6F?.parent).toBe(node10F); expect(node2F?.key).toBe(2); expect(node2F?.color).toBe(RBTNColor.RED); - expect(node2F?.left).toBe(tree.SENTINEL); - expect(node2F?.right).toBe(tree.SENTINEL); + expect(node2F?.left).toBe(rbTree.SENTINEL); + expect(node2F?.right).toBe(rbTree.SENTINEL); expect(node2F?.parent).toBe(node6F); expect(node15F?.key).toBe(15); expect(node15F?.color).toBe(RBTNColor.RED); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); + expect(node15F?.left).toBe(rbTree.SENTINEL); + expect(node15F?.right).toBe(rbTree.SENTINEL); expect(node15F?.parent).toBe(node21F); }); - it('should fix the tree after insertion', () => { - tree.add(1); - tree.add(2); - tree.add(5); - tree.add(15); - const node15F = tree.getNode(15); - expect(node15F?.left).toBe(tree.SENTINEL); - expect(node15F?.right).toBe(tree.SENTINEL); - expect(node15F?.parent).toBe(tree.getNode(5)); + it('should fix the rbTree after insertion', () => { + rbTree.add(1); + rbTree.add(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?.parent).toBe(rbTree.getNode(5)); - tree.add(25); - tree.add(10); - tree.add(8); - tree.add(28); - tree.add(111); - tree.add(12); - tree.delete(2); - tree.add(22); - tree.add(50); - tree.add(155); - tree.add(225); - const node225F = tree.getNode(225); - expect(node225F?.left).toBe(tree.SENTINEL); - expect(node225F?.right).toBe(tree.SENTINEL); + rbTree.add(25); + rbTree.add(10); + rbTree.add(8); + rbTree.add(28); + rbTree.add(111); + rbTree.add(12); + rbTree.delete(2); + rbTree.add(22); + rbTree.add(50); + 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?.parent?.key).toBe(155); - tree.add(7); - isDebug && tree.print(); + rbTree.add(7); + isDebug && rbTree.print(); - const node15S = tree.getNode(15); + const node15S = rbTree.getNode(15); expect(node15S?.left?.key).toBe(10); expect(node15S?.right?.key).toBe(25); - expect(tree.root).toBe(tree.getNode(8)); + expect(rbTree.root).toBe(rbTree.getNode(8)); expect(node15S?.parent?.key).toBe(28); - tree.delete(15); - expect(tree.root?.key).toBe(8); - expect(tree.root?.parent).toBe(undefined); + rbTree.delete(15); + expect(rbTree.root?.key).toBe(8); + expect(rbTree.root?.parent).toBe(undefined); - const node15T = tree.getNode(15); + const node15T = rbTree.getNode(15); expect(node15T).toBe(undefined); - tree.add(23); - tree.add(33); - tree.add(15); + rbTree.add(23); + rbTree.add(33); + rbTree.add(15); - const nodeLM = tree.getLeftMost(); + const nodeLM = rbTree.getLeftMost(); expect(nodeLM?.key).toBe(1); - const node50 = tree.getNode(50); + const node50 = rbTree.getNode(50); expect(node50?.key).toBe(50); expect(node50?.left?.key).toBe(33); - expect(node50?.right).toBe(tree.SENTINEL); - const node15Fo = tree.getNode(15); + expect(node50?.right).toBe(rbTree.SENTINEL); + const node15Fo = rbTree.getNode(15); expect(node15Fo?.key).toBe(15); - expect(node15Fo?.left).toBe(tree.SENTINEL); - const node225S = tree.getNode(225); - expect(node225S?.left).toBe(tree.SENTINEL); - expect(node225S?.right).toBe(tree.SENTINEL); + expect(node15Fo?.left).toBe(rbTree.SENTINEL); + const node225S = rbTree.getNode(225); + expect(node225S?.left).toBe(rbTree.SENTINEL); + expect(node225S?.right).toBe(rbTree.SENTINEL); expect(node225S?.parent?.key).toBe(155); // TODO - // expect(tree.getNode(0)).toBe(undefined); - tree.add(2); - tree.add(3); - tree.add(4); - tree.add(6); - tree.add(9); - tree.add(11); - tree.add(13); - tree.add(14); - tree.add(16); - tree.add(17); - tree.add(18); - tree.add(19); - tree.add(110); + // expect(rbTree.getNode(0)).toBe(undefined); + rbTree.add(2); + rbTree.add(3); + rbTree.add(4); + rbTree.add(6); + rbTree.add(9); + rbTree.add(11); + rbTree.add(13); + rbTree.add(14); + rbTree.add(16); + rbTree.add(17); + rbTree.add(18); + rbTree.add(19); + rbTree.add(110); - isDebug && tree.print(); + isDebug && rbTree.print(); - expect(tree.dfs()).toEqual([ + expect(rbTree.dfs()).toEqual([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 25, 28, 33, 50, 110, 111, 155, 225 ]); - expect(tree.isBST()).toBe(true); + expect(rbTree.isBST()).toBe(true); }); - it('should fix the tree after insertion and deletion', () => { + it('should fix the rbTree after insertion and deletion', () => { for (let i = 0; i < 100; i++) { - tree.add(i); + rbTree.add(i); } for (let i = 0; i < 49; i++) { - tree.delete(i); + rbTree.delete(i); } - expect(tree.size).toBe(51); - expect(tree.isBST()).toBe(true); - expect(tree.isBST(tree.root, IterationType.RECURSIVE)).toBe(true); + expect(rbTree.size).toBe(51); + expect(rbTree.isBST()).toBe(true); + expect(rbTree.isBST(rbTree.root, IterationType.RECURSIVE)).toBe(true); - expect(tree.dfs(n => n.key, 'in', tree.root, IterationType.ITERATIVE)).toEqual([ + expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.ITERATIVE)).toEqual([ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 ]); - expect(tree.dfs(n => n.key, 'in', tree.root, IterationType.RECURSIVE)).toEqual([ + expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.RECURSIVE)).toEqual([ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 ]); }); - it('should fix the tree after large scale insertion and deletion', () => { + it('should fix the rbTree after large scale insertion and deletion', () => { for (let i = 0; i < 10000; i++) { - tree.add(i); + rbTree.add(i); } for (let i = 0; i < 10000; i++) { - tree.delete(i); + rbTree.delete(i); } - expect(tree.size).toBe(0); - expect(tree.isBST()).toBe(true); - expect(tree.dfs(n => n.key, 'in', tree.root, IterationType.ITERATIVE)).toEqual([]); + expect(rbTree.size).toBe(0); + expect(rbTree.isBST()).toBe(true); + expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.ITERATIVE)).toEqual([]); - tree.clear(); + rbTree.clear(); for (let i = 0; i < 1000; i++) { - tree.add(getRandomInt(-100, 1000)); - tree.delete(getRandomInt(-100, 1000)); + rbTree.add(getRandomInt(-100, 1000)); + rbTree.delete(getRandomInt(-100, 1000)); } - // TODO there is a bug when dfs the tree with SENTINEL node - // expect(tree.isBST()).toBe(true); + // TODO there is a bug when dfs the rbTree with SENTINEL node + // expect(rbTree.isBST()).toBe(true); }); const { HUNDRED_THOUSAND } = magnitude; const arr = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND, true); const competitor = new OrderedMap(); - it('should fix the tree after large scale insertion and deletion', () => { - tree.clear(); + it('should fix the rbTree after large scale insertion and deletion', () => { + rbTree.clear(); const tS = performance.now(); for (let i = 0; i < arr.length; i++) { - tree.add(arr[i]); + rbTree.add(arr[i]); } isDebug && console.log(performance.now() - tS); @@ -531,20 +531,20 @@ describe('RedBlackTree 2', () => { }); it('duplicates', () => { - tree.addMany([9, 8, 7, 8, 8, 8, 2, 3, 6, 5, 5, 4]); - isDebug && tree.print(); + rbTree.addMany([9, 8, 7, 8, 8, 8, 2, 3, 6, 5, 5, 4]); + isDebug && rbTree.print(); - expect(tree.size).toBe(8); - expect(tree.isBST()).toBe(true); - expect(tree.isAVLBalanced()).toBe(true); - tree.addMany([10, 5, 2, 11]); - expect(tree.size).toBe(10); - expect(tree.isBST()).toBe(true); - expect(tree.isAVLBalanced()).toBe(true); + expect(rbTree.size).toBe(8); + expect(rbTree.isBST()).toBe(true); + expect(rbTree.isAVLBalanced()).toBe(true); + rbTree.addMany([10, 5, 2, 11]); + expect(rbTree.size).toBe(10); + expect(rbTree.isBST()).toBe(true); + expect(rbTree.isAVLBalanced()).toBe(true); - tree.clear(); - tree.addMany([10, 20, 30, 40, 50, 60]); - expect(tree.isAVLBalanced()).toBe(false); + rbTree.clear(); + rbTree.addMany([10, 20, 30, 40, 50, 60]); + expect(rbTree.isAVLBalanced()).toBe(false); }); describe('RedBlackTree delete test', function () { @@ -598,7 +598,7 @@ describe('RedBlackTree 2', () => { if (rbTree.root) dfs(rbTree.root); expect(rbTree.size).toBe(0); - expect(rbTree.getHeight()).toBe(0); + expect(rbTree.getHeight()).toBe(-1); expect(nanCount).toBeLessThanOrEqual(inputSize); isDebug && rbTree.print(); @@ -633,7 +633,7 @@ describe('RedBlackTree 2', () => { expect(mockCallback.mock.calls[2]).toEqual(['c', 3]); }); - test('filter should return a new tree with filtered elements', () => { + test('filter should return a new rbTree with filtered elements', () => { const filteredTree = rbTree.filter((value, key) => key > 1); expect(filteredTree.size).toBe(2); expect([...filteredTree]).toEqual([ @@ -642,7 +642,7 @@ describe('RedBlackTree 2', () => { ]); }); - test('map should return a new tree with modified elements', () => { + test('map should return a new rbTree with modified elements', () => { const mappedTree = rbTree.map((value, key) => (key * 2).toString()); expect(mappedTree.size).toBe(3); expect([...mappedTree]).toEqual([ diff --git a/test/unit/data-structures/binary-tree/tree-multi-map.test.ts b/test/unit/data-structures/binary-tree/tree-multi-map.test.ts index db2f410..b619340 100644 --- a/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +++ b/test/unit/data-structures/binary-tree/tree-multi-map.test.ts @@ -14,12 +14,13 @@ const isDebug = isDebugTest; // const isDebug = true; describe('TreeMultiMap count', () => { - let tm: TreeMultiMap; + let tmm: TreeMultiMap; beforeEach(() => { - tm = new TreeMultiMap(); + tmm = new TreeMultiMap(); }); - it('Should added isolated node count ', () => { - tm.addMany([ + + it('Should added node count ', () => { + tmm.addMany([ [1, 1], [2, 2], [3, 3], @@ -27,35 +28,45 @@ describe('TreeMultiMap count', () => { [5, 5] ]); const newNode = new TreeMultiMapNode(3, 33, 10); - tm.add(newNode); - expect(tm.count).toBe(15); - expect(tm.getMutableCount()).toBe(15); - expect(tm.getNode(3)?.count).toBe(11); + tmm.add(newNode); + expect(tmm.count).toBe(15); + expect(tmm.getMutableCount()).toBe(15); + expect(tmm.getNode(3)?.count).toBe(11); }); it('Should count', () => { - tm.addMany([ + tmm.addMany([ [1, 1], [2, 2], [3, 3] ]); - tm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1); - expect(tm.getMutableCount()).toBe(7); - expect(tm.count).toBe(3); + tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1); + expect(tmm.getMutableCount()).toBe(7); + expect(tmm.count).toBe(3); }); }); describe('TreeMultiMap operations test1', () => { + it('should height ', () => { + const tmm = new TreeMultiMap(); + expect(tmm.getHeight()).toBe(-1); + expect(tmm.getMinHeight()).toBe(-1); + + tmm.addMany([1, 6, 7, 2, 3, 4, 9, 11, 8, 5, 10, 12, 16, 14, 13, 15]); + expect(tmm.getHeight()).toBe(5); + expect(tmm.getMinHeight()).toBe(2); + }); + it('should size and count', () => { - const treeMultiMap = new TreeMultiMap(); + const tmm = new TreeMultiMap(); - expect(treeMultiMap instanceof TreeMultiMap); + expect(tmm instanceof TreeMultiMap); - treeMultiMap.add([11, 11]); - treeMultiMap.add([3, 3]); - expect(treeMultiMap.count).toBe(2); - expect(treeMultiMap.getMutableCount()).toBe(2); - expect(treeMultiMap.size).toBe(2); + tmm.add([11, 11]); + tmm.add([3, 3]); + expect(tmm.count).toBe(2); + expect(tmm.getMutableCount()).toBe(2); + expect(tmm.size).toBe(2); const keyValuePairs: [number, number][] = [ [11, 11], @@ -76,25 +87,25 @@ describe('TreeMultiMap operations test1', () => { [5, 5] ]; - treeMultiMap.addMany(keyValuePairs); - expect(treeMultiMap.size).toBe(16); - expect(treeMultiMap.count).toBe(18); - expect(treeMultiMap.getMutableCount()).toBe(18); - treeMultiMap.delete(11); - expect(treeMultiMap.count).toBe(17); - expect(treeMultiMap.getMutableCount()).toBe(17); - treeMultiMap.delete(3, undefined, true); - expect(treeMultiMap.count).toBe(15); - expect(treeMultiMap.getMutableCount()).toBe(15); + tmm.addMany(keyValuePairs); + expect(tmm.size).toBe(16); + expect(tmm.count).toBe(18); + expect(tmm.getMutableCount()).toBe(18); + tmm.delete(11); + expect(tmm.count).toBe(17); + expect(tmm.getMutableCount()).toBe(17); + tmm.delete(3, undefined, true); + expect(tmm.count).toBe(15); + expect(tmm.getMutableCount()).toBe(15); }); it('should perform various operations on a Binary Search Tree with numeric values1', () => { - const treeMultiMap = new TreeMultiMap(); + const tmm = new TreeMultiMap(); - expect(treeMultiMap instanceof TreeMultiMap); + expect(tmm instanceof TreeMultiMap); - treeMultiMap.add([11, 11]); - treeMultiMap.add([3, 3]); + tmm.add([11, 11]); + tmm.add([3, 3]); const idAndValues: [number, number][] = [ [11, 11], [3, 3], @@ -113,201 +124,200 @@ describe('TreeMultiMap operations test1', () => { [10, 10], [5, 5] ]; - treeMultiMap.addMany(idAndValues); - expect(treeMultiMap.root instanceof TreeMultiMapNode); + tmm.addMany(idAndValues); + expect(tmm.root instanceof TreeMultiMapNode); - if (treeMultiMap.root) expect(treeMultiMap.root.key == 11); + if (tmm.root) expect(tmm.root.key == 11); - expect(treeMultiMap.size).toBe(16); - expect(treeMultiMap.count).toBe(18); - expect(treeMultiMap.getMutableCount()).toBe(18); + expect(tmm.size).toBe(16); + expect(tmm.count).toBe(18); + expect(tmm.getMutableCount()).toBe(18); - expect(treeMultiMap.has(6)); - isDebug && treeMultiMap.print(); - expect(treeMultiMap.getHeight(6)).toBe(1); - expect(treeMultiMap.getDepth(6)).toBe(3); - const nodeId10 = treeMultiMap.getNode(10); + expect(tmm.has(6)); + isDebug && tmm.print(); + expect(tmm.getHeight(6)).toBe(1); + expect(tmm.getDepth(6)).toBe(3); + const nodeId10 = tmm.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = treeMultiMap.getNode(9, node => node.value); + const nodeVal9 = tmm.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); - const nodesByCount1 = treeMultiMap.getNodes(1, node => node.count); + const nodesByCount1 = tmm.getNodes(1, node => node.count); expect(nodesByCount1.length).toBe(14); - const nodesByCount2 = treeMultiMap.getNodes(2, node => node.count); + const nodesByCount2 = tmm.getNodes(2, node => node.count); expect(nodesByCount2.length).toBe(2); - const leftMost = treeMultiMap.getLeftMost(); + const leftMost = tmm.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = treeMultiMap.getNode(15); - const minNodeBySpecificNode = node15 && treeMultiMap.getLeftMost(node15); + const node15 = tmm.getNode(15); + const minNodeBySpecificNode = node15 && tmm.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(14); let subTreeSum = 0; - node15 && treeMultiMap.dfs(node => (subTreeSum += node.key), 'pre', 15); + node15 && tmm.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(45); let lesserSum = 0; - treeMultiMap.lesserOrGreaterTraverse((node: TreeMultiMapNode) => (lesserSum += node.key), CP.lt, 10); + tmm.lesserOrGreaterTraverse((node: TreeMultiMapNode) => (lesserSum += node.key), CP.lt, 10); expect(lesserSum).toBe(45); expect(node15 instanceof TreeMultiMapNode); if (node15 instanceof TreeMultiMapNode) { - const subTreeAdd = treeMultiMap.dfs(node => (node.count += 1), 'pre', 15); + const subTreeAdd = tmm.dfs(node => (node.count += 1), 'pre', 15); expect(subTreeAdd); } - const node11 = treeMultiMap.getNode(11); + const node11 = tmm.getNode(11); expect(node11 instanceof TreeMultiMapNode); if (node11 instanceof TreeMultiMapNode) { - const allGreaterNodesAdded = treeMultiMap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); + const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); expect(allGreaterNodesAdded); } - const dfsInorderNodes = treeMultiMap.dfs(node => node, 'in'); + const dfsInorderNodes = tmm.dfs(node => node, 'in'); expect(dfsInorderNodes[0].key).toBe(1); expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16); + expect(tmm.isPerfectlyBalanced()).toBe(false); + tmm.perfectlyBalance(); + expect(tmm.isPerfectlyBalanced()).toBe(false); - expect(treeMultiMap.isPerfectlyBalanced()).toBe(true); - treeMultiMap.perfectlyBalance(); - expect(treeMultiMap.isPerfectlyBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - - const bfsNodesAfterBalanced = treeMultiMap.bfs(node => node); + const bfsNodesAfterBalanced = tmm.bfs(node => node); expect(bfsNodesAfterBalanced[0].key).toBe(6); expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16); - const removed11 = treeMultiMap.delete(11, undefined, true); + const removed11 = tmm.delete(11, undefined, true); expect(removed11 instanceof Array); expect(removed11[0]); expect(removed11[0].deleted); if (removed11[0].deleted) expect(removed11[0].deleted.key).toBe(11); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight(15)).toBe(1); + expect(tmm.getHeight(15)).toBe(1); - const removed1 = treeMultiMap.delete(1, undefined, true); + const removed1 = tmm.delete(1, undefined, true); expect(removed1 instanceof Array); expect(removed1[0]); expect(removed1[0].deleted); if (removed1[0].deleted) expect(removed1[0].deleted.key).toBe(1); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(5); + expect(tmm.getHeight()).toBe(5); - const removed4 = treeMultiMap.delete(4, undefined, true); + const removed4 = tmm.delete(4, undefined, true); expect(removed4 instanceof Array); expect(removed4[0]); expect(removed4[0].deleted); if (removed4[0].deleted) expect(removed4[0].deleted.key).toBe(4); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(5); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(5); - const removed10 = treeMultiMap.delete(10, undefined, true); + const removed10 = tmm.delete(10, undefined, true); expect(removed10 instanceof Array); expect(removed10[0]); expect(removed10[0].deleted); if (removed10[0].deleted) expect(removed10[0].deleted.key).toBe(10); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(4); + expect(tmm.getHeight()).toBe(4); - const removed15 = treeMultiMap.delete(15, undefined, true); + const removed15 = tmm.delete(15, undefined, true); expect(removed15 instanceof Array); expect(removed15[0]); expect(removed15[0].deleted); if (removed15[0].deleted) expect(removed15[0].deleted.key).toBe(15); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed5 = treeMultiMap.delete(5, undefined, true); + const removed5 = tmm.delete(5, undefined, true); expect(removed5 instanceof Array); expect(removed5[0]); expect(removed5[0].deleted); if (removed5[0].deleted) expect(removed5[0].deleted.key).toBe(5); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(3); - const removed13 = treeMultiMap.delete(13, undefined, true); + const removed13 = tmm.delete(13, undefined, true); expect(removed13 instanceof Array); expect(removed13[0]); expect(removed13[0].deleted); if (removed13[0].deleted) expect(removed13[0].deleted.key).toBe(13); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(3); - const removed3 = treeMultiMap.delete(3, undefined, true); + const removed3 = tmm.delete(3, undefined, true); expect(removed3 instanceof Array); expect(removed3[0]); expect(removed3[0].deleted); if (removed3[0].deleted) expect(removed3[0].deleted.key).toBe(3); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed8 = treeMultiMap.delete(8, undefined, true); + const removed8 = tmm.delete(8, undefined, true); expect(removed8 instanceof Array); expect(removed8[0]); expect(removed8[0].deleted); if (removed8[0].deleted) expect(removed8[0].deleted.key).toBe(8); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed6 = treeMultiMap.delete(6, undefined, true); + const removed6 = tmm.delete(6, undefined, true); expect(removed6 instanceof Array); expect(removed6[0]); expect(removed6[0].deleted); if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6); - expect(treeMultiMap.delete(6, undefined, true).length).toBe(0); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.delete(6, undefined, true).length).toBe(0); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.getHeight()).toBe(3); - const removed7 = treeMultiMap.delete(7, undefined, true); + const removed7 = tmm.delete(7, undefined, true); expect(removed7 instanceof Array); expect(removed7[0]); expect(removed7[0].deleted); if (removed7[0].deleted) expect(removed7[0].deleted.key).toBe(7); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed9 = treeMultiMap.delete(9, undefined, true); + const removed9 = tmm.delete(9, undefined, true); expect(removed9 instanceof Array); expect(removed9[0]); expect(removed9[0].deleted); if (removed9[0].deleted) expect(removed9[0].deleted.key).toBe(9); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(2); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(2); - const removed14 = treeMultiMap.delete(14, undefined, true); + const removed14 = tmm.delete(14, undefined, true); expect(removed14 instanceof Array); expect(removed14[0]); expect(removed14[0].deleted); if (removed14[0].deleted) expect(removed14[0].deleted.key).toBe(14); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(1); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(1); - expect(treeMultiMap.isAVLBalanced()).toBe(true); + expect(tmm.isAVLBalanced()).toBe(true); - const bfsIDs = treeMultiMap.bfs(node => node.key); + const bfsIDs = tmm.bfs(node => node.key); expect(bfsIDs[0]).toBe(12); expect(bfsIDs[1]).toBe(2); expect(bfsIDs[2]).toBe(16); - const bfsNodes = treeMultiMap.bfs(node => node); + const bfsNodes = tmm.bfs(node => node); expect(bfsNodes[0].key).toBe(12); expect(bfsNodes[1].key).toBe(2); expect(bfsNodes[2].key).toBe(16); - expect(treeMultiMap.count).toBe(6); - expect(treeMultiMap.getMutableCount()).toBe(8); + expect(tmm.count).toBe(6); + expect(tmm.getMutableCount()).toBe(8); }); it('should perform various operations on a Binary Search Tree with object values', () => { @@ -347,11 +357,11 @@ describe('TreeMultiMap operations test1', () => { describe('TreeMultiMap operations test recursively1', () => { it('should perform various operations on a Binary Search Tree with numeric values1', () => { - const treeMultiMap = new TreeMultiMap([], { iterationType: IterationType.RECURSIVE }); + const tmm = new TreeMultiMap([], { iterationType: IterationType.RECURSIVE }); - expect(treeMultiMap instanceof TreeMultiMap); - treeMultiMap.add([11, 11]); - treeMultiMap.add([3, 3]); + expect(tmm instanceof TreeMultiMap); + tmm.add([11, 11]); + tmm.add([3, 3]); const idAndValues: [number, number][] = [ [11, 11], [3, 3], @@ -370,43 +380,43 @@ describe('TreeMultiMap operations test recursively1', () => { [10, 10], [5, 5] ]; - treeMultiMap.addMany(idAndValues); - expect(treeMultiMap.root).toBeInstanceOf(TreeMultiMapNode); + tmm.addMany(idAndValues); + expect(tmm.root).toBeInstanceOf(TreeMultiMapNode); - if (treeMultiMap.root) expect(treeMultiMap.root.key).toBe(5); + if (tmm.root) expect(tmm.root.key).toBe(5); - expect(treeMultiMap.size).toBe(16); - expect(treeMultiMap.count).toBe(18); - expect(treeMultiMap.getMutableCount()).toBe(18); + expect(tmm.size).toBe(16); + expect(tmm.count).toBe(18); + expect(tmm.getMutableCount()).toBe(18); - expect(treeMultiMap.has(6)); + expect(tmm.has(6)); - expect(treeMultiMap.getHeight(6)).toBe(1); - expect(treeMultiMap.getDepth(6)).toBe(3); - const nodeId10 = treeMultiMap.getNode(10); + expect(tmm.getHeight(6)).toBe(1); + expect(tmm.getDepth(6)).toBe(3); + const nodeId10 = tmm.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = treeMultiMap.getNode(9, node => node.value); + const nodeVal9 = tmm.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); - const nodesByCount1 = treeMultiMap.getNodes(1, node => node.count); + const nodesByCount1 = tmm.getNodes(1, node => node.count); expect(nodesByCount1.length).toBe(14); - const nodesByCount2 = treeMultiMap.getNodes(2, node => node.count); + const nodesByCount2 = tmm.getNodes(2, node => node.count); expect(nodesByCount2.length).toBe(2); - const leftMost = treeMultiMap.getLeftMost(); + const leftMost = tmm.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = treeMultiMap.getNode(15); - const minNodeBySpecificNode = node15 && treeMultiMap.getLeftMost(node15); + const node15 = tmm.getNode(15); + const minNodeBySpecificNode = node15 && tmm.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(14); let subTreeSum = 0; - node15 && treeMultiMap.dfs(node => (subTreeSum += node.key), 'pre', 15); + node15 && tmm.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(45); let lesserSum = 0; - expect(treeMultiMap.has(9)).toBe(true); - treeMultiMap.lesserOrGreaterTraverse( + expect(tmm.has(9)).toBe(true); + tmm.lesserOrGreaterTraverse( node => { lesserSum += node.key; return node.key; @@ -418,161 +428,161 @@ describe('TreeMultiMap operations test recursively1', () => { expect(node15 instanceof TreeMultiMapNode); if (node15 instanceof TreeMultiMapNode) { - const subTreeAdd = treeMultiMap.dfs(node => (node.count += 1), 'pre', 15); + const subTreeAdd = tmm.dfs(node => (node.count += 1), 'pre', 15); expect(subTreeAdd); } - const node11 = treeMultiMap.getNode(11); + const node11 = tmm.getNode(11); expect(node11 instanceof TreeMultiMapNode); if (node11 instanceof TreeMultiMapNode) { - const allGreaterNodesAdded = treeMultiMap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); + const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); expect(allGreaterNodesAdded); } - const dfsInorderNodes = treeMultiMap.dfs(node => node, 'in'); + const dfsInorderNodes = tmm.dfs(node => node, 'in'); expect(dfsInorderNodes[0].key).toBe(1); expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16); - expect(treeMultiMap.isPerfectlyBalanced()).toBe(true); + expect(tmm.isPerfectlyBalanced()).toBe(false); - treeMultiMap.perfectlyBalance(); + tmm.perfectlyBalance(); - expect(treeMultiMap.isPerfectlyBalanced()).toBe(false); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isPerfectlyBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - const bfsNodesAfterBalanced = treeMultiMap.bfs(node => node); + const bfsNodesAfterBalanced = tmm.bfs(node => node); expect(bfsNodesAfterBalanced[0].key).toBe(6); expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16); - const removed11 = treeMultiMap.delete(11, undefined, true); + const removed11 = tmm.delete(11, undefined, true); expect(removed11 instanceof Array); expect(removed11[0]); expect(removed11[0].deleted); if (removed11[0].deleted) expect(removed11[0].deleted.key).toBe(11); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight(15)).toBe(1); + expect(tmm.getHeight(15)).toBe(1); - const removed1 = treeMultiMap.delete(1, undefined, true); + const removed1 = tmm.delete(1, undefined, true); expect(removed1 instanceof Array); expect(removed1[0]); expect(removed1[0].deleted); if (removed1[0].deleted) expect(removed1[0].deleted.key).toBe(1); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(5); + expect(tmm.getHeight()).toBe(5); - const removed4 = treeMultiMap.delete(4, undefined, true); + const removed4 = tmm.delete(4, undefined, true); expect(removed4 instanceof Array); expect(removed4[0]); expect(removed4[0].deleted); if (removed4[0].deleted) expect(removed4[0].deleted.key).toBe(4); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(5); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(5); - const removed10 = treeMultiMap.delete(10, undefined, true); + const removed10 = tmm.delete(10, undefined, true); expect(removed10 instanceof Array); expect(removed10[0]); expect(removed10[0].deleted); if (removed10[0].deleted) expect(removed10[0].deleted.key).toBe(10); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(4); + expect(tmm.getHeight()).toBe(4); - const removed15 = treeMultiMap.delete(15, undefined, true); + const removed15 = tmm.delete(15, undefined, true); expect(removed15 instanceof Array); expect(removed15[0]); expect(removed15[0].deleted); if (removed15[0].deleted) expect(removed15[0].deleted.key).toBe(15); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed5 = treeMultiMap.delete(5, undefined, true); + const removed5 = tmm.delete(5, undefined, true); expect(removed5 instanceof Array); expect(removed5[0]); expect(removed5[0].deleted); if (removed5[0].deleted) expect(removed5[0].deleted.key).toBe(5); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(3); - const removed13 = treeMultiMap.delete(13, undefined, true); + const removed13 = tmm.delete(13, undefined, true); expect(removed13 instanceof Array); expect(removed13[0]); expect(removed13[0].deleted); if (removed13[0].deleted) expect(removed13[0].deleted.key).toBe(13); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(3); - const removed3 = treeMultiMap.delete(3, undefined, true); + const removed3 = tmm.delete(3, undefined, true); expect(removed3 instanceof Array); expect(removed3[0]); expect(removed3[0].deleted); if (removed3[0].deleted) expect(removed3[0].deleted.key).toBe(3); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed8 = treeMultiMap.delete(8, undefined, true); + const removed8 = tmm.delete(8, undefined, true); expect(removed8 instanceof Array); expect(removed8[0]); expect(removed8[0].deleted); if (removed8[0].deleted) expect(removed8[0].deleted.key).toBe(8); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed6 = treeMultiMap.delete(6, undefined, true); + const removed6 = tmm.delete(6, undefined, true); expect(removed6 instanceof Array); expect(removed6[0]); expect(removed6[0].deleted); if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6); - expect(treeMultiMap.delete(6, undefined, true).length).toBe(0); - expect(treeMultiMap.isAVLBalanced()).toBe(false); + expect(tmm.delete(6, undefined, true).length).toBe(0); + expect(tmm.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.getHeight()).toBe(3); - const removed7 = treeMultiMap.delete(7, undefined, true); + const removed7 = tmm.delete(7, undefined, true); expect(removed7 instanceof Array); expect(removed7[0]); expect(removed7[0].deleted); if (removed7[0].deleted) expect(removed7[0].deleted.key).toBe(7); - expect(treeMultiMap.isAVLBalanced()).toBe(false); - expect(treeMultiMap.getHeight()).toBe(3); + expect(tmm.isAVLBalanced()).toBe(false); + expect(tmm.getHeight()).toBe(3); - const removed9 = treeMultiMap.delete(9, undefined, true); + const removed9 = tmm.delete(9, undefined, true); expect(removed9 instanceof Array); expect(removed9[0]); expect(removed9[0].deleted); if (removed9[0].deleted) expect(removed9[0].deleted.key).toBe(9); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(2); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(2); - const removed14 = treeMultiMap.delete(14, undefined, true); + const removed14 = tmm.delete(14, undefined, true); expect(removed14 instanceof Array); expect(removed14[0]); expect(removed14[0].deleted); if (removed14[0].deleted) expect(removed14[0].deleted.key).toBe(14); - expect(treeMultiMap.isAVLBalanced()).toBe(true); - expect(treeMultiMap.getHeight()).toBe(1); + expect(tmm.isAVLBalanced()).toBe(true); + expect(tmm.getHeight()).toBe(1); - expect(treeMultiMap.isAVLBalanced()).toBe(true); + expect(tmm.isAVLBalanced()).toBe(true); - const bfsIDs = treeMultiMap.bfs(node => node.key); + const bfsIDs = tmm.bfs(node => node.key); expect(bfsIDs[0]).toBe(12); expect(bfsIDs[1]).toBe(2); expect(bfsIDs[2]).toBe(16); - const bfsNodes = treeMultiMap.bfs(node => node); + const bfsNodes = tmm.bfs(node => node); expect(bfsNodes[0].key).toBe(12); expect(bfsNodes[1].key).toBe(2); expect(bfsNodes[2].key).toBe(16); - expect(treeMultiMap.count).toBe(6); - expect(treeMultiMap.getMutableCount()).toBe(8); + expect(tmm.count).toBe(6); + expect(tmm.getMutableCount()).toBe(8); }); it('should perform various operations on a Binary Search Tree with object values', () => { @@ -611,79 +621,81 @@ describe('TreeMultiMap operations test recursively1', () => { }); describe('TreeMultiMap delete test', function () { - const treeMS = new TreeMultiMap(); - const inputSize = 100; // Adjust input sizes as needed + const tmm = new TreeMultiMap(); + const inputSize = 1000; // Adjust input sizes as needed beforeEach(() => { - treeMS.clear(); + tmm.clear(); }); it(`Observe the time consumption of TreeMultiMap.dfs be good`, function () { const startDFS = performance.now(); - const dfs = treeMS.dfs(node => node); + const dfs = tmm.dfs(node => node); isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length); }); it('The structure remains normal after random deletion', function () { for (let i = 0; i < inputSize; i++) { - treeMS.add(i); + tmm.add(i); } + expect(tmm.size).toBe(inputSize); + for (let i = 0; i < inputSize; i++) { const num = getRandomInt(0, inputSize - 1); - treeMS.delete(num); + tmm.delete(num); } - let nanCount = 0; + let nilCount = 0; const dfs = (cur: TreeMultiMapNode) => { - if (isNaN(cur.key)) nanCount++; + if (isNaN(cur.key)) nilCount++; if (cur.left) dfs(cur.left); if (cur.right) dfs(cur.right); }; - if (treeMS.root) dfs(treeMS.root); + if (tmm.root) dfs(tmm.root); - expect(treeMS.size).toBeLessThanOrEqual(inputSize); - expect(treeMS.getHeight()).toBeGreaterThan(Math.log2(inputSize)); - expect(treeMS.getHeight()).toBeLessThan(Math.log2(inputSize) * 2); + expect(tmm.size).toBeLessThanOrEqual(inputSize); + expect(tmm.getHeight()).toBeGreaterThan(Math.log2(inputSize) - 1); + expect(tmm.getHeight()).toBeLessThan(Math.log2(inputSize) * 2); - expect(nanCount).toBeLessThanOrEqual(inputSize); + expect(nilCount).toBe(tmm.size + 1); }); it(`Random additions, complete deletions of structures are normal`, function () { for (let i = 0; i < inputSize; i++) { const num = getRandomInt(0, inputSize - 1); if (i === 0 && isDebug) console.log(`first:`, num); - treeMS.add(num); + tmm.add(num); } for (let i = 0; i < inputSize; i++) { - treeMS.delete(i, undefined, true); + tmm.delete(i, undefined, true); } - let nanCount = 0; + let nilCount = 0; const dfs = (cur: TreeMultiMapNode) => { - if (isNaN(cur.key)) nanCount++; + if (isNaN(cur.key)) nilCount++; if (cur.left) dfs(cur.left); if (cur.right) dfs(cur.right); }; - if (treeMS.root) dfs(treeMS.root); + if (tmm.root) dfs(tmm.root); - expect(treeMS.size).toBe(0); - expect(treeMS.getHeight()).toBe(0); - expect(nanCount).toBeLessThanOrEqual(inputSize); + expect(tmm.size).toBe(0); + expect(tmm.getHeight()).toBe(-1); + expect(nilCount).toBe(tmm.size + 1); - isDebug && treeMS.print(); + isDebug && tmm.print(); }); it(`Random additions, count deletions of structures are normal`, function () { for (let i = 0; i < inputSize; i++) { const num = getRandomInt(0, inputSize - 1); if (i === 0 && isDebug) console.log(`first:`, num); - treeMS.add(num); + tmm.add(num); } for (let i = 0; i < inputSize; i++) { - treeMS.delete(i); + tmm.delete(i); } let nanCount = 0; @@ -692,49 +704,49 @@ describe('TreeMultiMap delete test', function () { if (cur.left) dfs(cur.left); if (cur.right) dfs(cur.right); }; - if (treeMS.root) dfs(treeMS.root); + if (tmm.root) dfs(tmm.root); - expect(treeMS.size).toBeGreaterThanOrEqual(0); - expect(treeMS.getHeight()).toBeGreaterThanOrEqual(0); + expect(tmm.size).toBeGreaterThanOrEqual(0); + expect(tmm.getHeight()).toBeGreaterThanOrEqual(0); expect(nanCount).toBeLessThanOrEqual(inputSize); - isDebug && treeMS.print(); + isDebug && tmm.print(); }); it('should the clone method', () => { - function checkTreeStructure(treeMultiMap: TreeMultiMap) { - expect(treeMultiMap.size).toBe(4); - expect(treeMultiMap.root?.key).toBe('2'); - expect(treeMultiMap.root?.left?.key).toBe('1'); - expect(treeMultiMap.root?.left?.left?.key).toBe(NaN); - expect(treeMultiMap.root?.left?.right?.key).toBe(NaN); - expect(treeMultiMap.root?.right?.key).toBe('4'); - expect(treeMultiMap.root?.right?.left?.key).toBe(NaN); - expect(treeMultiMap.root?.right?.right?.key).toBe('5'); + function checkTreeStructure(tmm: TreeMultiMap) { + expect(tmm.size).toBe(4); + expect(tmm.root?.key).toBe('2'); + expect(tmm.root?.left?.key).toBe('1'); + expect(tmm.root?.left?.left?.key).toBe(NaN); + expect(tmm.root?.left?.right?.key).toBe(NaN); + expect(tmm.root?.right?.key).toBe('4'); + expect(tmm.root?.right?.left?.key).toBe(NaN); + expect(tmm.root?.right?.right?.key).toBe('5'); } - const treeMultiMap = new TreeMultiMap(); - treeMultiMap.addMany([ + const tmm = new TreeMultiMap(); + tmm.addMany([ ['2', 2], ['4', 4], ['5', 5], ['3', 3], ['1', 1] ]); - expect(treeMultiMap.size).toBe(5); - expect(treeMultiMap.root?.key).toBe('2'); - expect(treeMultiMap.root?.left?.key).toBe('1'); - expect(treeMultiMap.root?.left?.left?.key).toBe(NaN); - expect(treeMultiMap.root?.left?.right?.key).toBe(NaN); - expect(treeMultiMap.root?.right?.key).toBe('4'); - expect(treeMultiMap.root?.right?.left?.key).toBe(`3`); - expect(treeMultiMap.root?.right?.right?.key).toBe('5'); - treeMultiMap.delete('3'); - checkTreeStructure(treeMultiMap); - const cloned = treeMultiMap.clone(); + expect(tmm.size).toBe(5); + expect(tmm.root?.key).toBe('2'); + expect(tmm.root?.left?.key).toBe('1'); + expect(tmm.root?.left?.left?.key).toBe(NaN); + expect(tmm.root?.left?.right?.key).toBe(NaN); + expect(tmm.root?.right?.key).toBe('4'); + expect(tmm.root?.right?.left?.key).toBe(`3`); + expect(tmm.root?.right?.right?.key).toBe('5'); + tmm.delete('3'); + checkTreeStructure(tmm); + const cloned = tmm.clone(); checkTreeStructure(cloned); cloned.delete('1'); - expect(treeMultiMap.size).toBe(4); + expect(tmm.size).toBe(4); expect(cloned.size).toBe(3); }); });