mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
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.
This commit is contained in:
parent
644ce69190
commit
a653d465fa
|
@ -1021,7 +1021,7 @@ export class BinaryTree<
|
|||
*/
|
||||
getHeight(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = 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<NODE, number> = 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<K, V, NODE> = 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<K, V, NODE> = 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;
|
||||
|
|
|
@ -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<NODE>([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<NODE>([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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -8,136 +8,136 @@ const isDebug = isDebugTest;
|
|||
// const isDebug = true;
|
||||
|
||||
describe('RedBlackTree 1', () => {
|
||||
let tree: RedBlackTree<number>;
|
||||
let rbTree: RedBlackTree<number>;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = new RedBlackTree<number>();
|
||||
rbTree = new RedBlackTree<number>();
|
||||
});
|
||||
|
||||
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<number>;
|
||||
let rbTree: RedBlackTree<number>;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = new RedBlackTree<number>();
|
||||
rbTree = new RedBlackTree<number>();
|
||||
});
|
||||
|
||||
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<number, number>();
|
||||
|
||||
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([
|
||||
|
|
|
@ -14,12 +14,13 @@ const isDebug = isDebugTest;
|
|||
// const isDebug = true;
|
||||
|
||||
describe('TreeMultiMap count', () => {
|
||||
let tm: TreeMultiMap<number>;
|
||||
let tmm: TreeMultiMap<number>;
|
||||
beforeEach(() => {
|
||||
tm = new TreeMultiMap<number>();
|
||||
tmm = new TreeMultiMap<number>();
|
||||
});
|
||||
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<number>) => (lesserSum += node.key), CP.lt, 10);
|
||||
tmm.lesserOrGreaterTraverse((node: TreeMultiMapNode<number>) => (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<number>([], { iterationType: IterationType.RECURSIVE });
|
||||
const tmm = new TreeMultiMap<number>([], { 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<number, number>();
|
||||
const inputSize = 100; // Adjust input sizes as needed
|
||||
const tmm = new TreeMultiMap<number, number>();
|
||||
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<number>) => {
|
||||
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<number>) => {
|
||||
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<string, number>) {
|
||||
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<string, number>) {
|
||||
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<string, number>();
|
||||
treeMultiMap.addMany([
|
||||
const tmm = new TreeMultiMap<string, number>();
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue