efactor: completely eliminate the use of enumerations

This commit is contained in:
Revone 2024-01-14 19:49:50 +08:00
parent 25de27cf6c
commit 76df347da5
19 changed files with 241 additions and 195 deletions

View file

@ -86,7 +86,20 @@ export class AVLTreeMultiMap<
return this._count;
}
getMutableCount(): number {
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*/
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The function calculates the sum of the count property of all nodes in a tree using depth-first
* search.
* @returns the sum of the count property of all nodes in the tree.
*/
getComputedCount(): number {
let sum = 0;
this.dfs(node => (sum += node.count));
return sum;
@ -318,7 +331,7 @@ export class AVLTreeMultiMap<
* @returns a boolean value.
*/
override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
const sorted = this.dfs(node => node, 'in'),
const sorted = this.dfs(node => node, 'IN'),
n = sorted.length;
if (sorted.length < 1) return false;

View file

@ -1352,7 +1352,7 @@ export class BinaryTree<
*/
dfs<C extends BTNCallback<NODE | null | undefined>>(
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
pattern: DFSOrderPattern = 'IN',
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType: IterationType = 'ITERATIVE',
includeNull = false
@ -1363,7 +1363,7 @@ export class BinaryTree<
if (iterationType === 'RECURSIVE') {
const _traverse = (node: NODE | null | undefined) => {
switch (pattern) {
case 'in':
case 'IN':
if (includeNull) {
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
this.isNodeOrNull(node) && ans.push(callback(node));
@ -1374,7 +1374,7 @@ export class BinaryTree<
if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
}
break;
case 'pre':
case 'PRE':
if (includeNull) {
this.isNodeOrNull(node) && ans.push(callback(node));
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
@ -1385,7 +1385,7 @@ export class BinaryTree<
if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
}
break;
case 'post':
case 'POST':
if (includeNull) {
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right);
@ -1417,17 +1417,17 @@ export class BinaryTree<
ans.push(callback(cur.node));
} else {
switch (pattern) {
case 'in':
case 'IN':
cur.node && stack.push({ opt: 0, node: cur.node.right });
stack.push({ opt: 1, node: cur.node });
cur.node && stack.push({ opt: 0, node: cur.node.left });
break;
case 'pre':
case 'PRE':
cur.node && stack.push({ opt: 0, node: cur.node.right });
cur.node && stack.push({ opt: 0, node: cur.node.left });
stack.push({ opt: 1, node: cur.node });
break;
case 'post':
case 'POST':
stack.push({ opt: 1, node: cur.node });
cur.node && stack.push({ opt: 0, node: cur.node.right });
cur.node && stack.push({ opt: 0, node: cur.node.left });
@ -1652,7 +1652,7 @@ export class BinaryTree<
*/
morris<C extends BTNCallback<NODE>>(
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
pattern: DFSOrderPattern = 'IN',
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
@ -1681,7 +1681,7 @@ export class BinaryTree<
_reverseEdge(tail);
};
switch (pattern) {
case 'in':
case 'IN':
while (cur) {
if (cur.left) {
const predecessor = this.getPredecessor(cur);
@ -1697,7 +1697,7 @@ export class BinaryTree<
cur = cur.right;
}
break;
case 'pre':
case 'PRE':
while (cur) {
if (cur.left) {
const predecessor = this.getPredecessor(cur);
@ -1715,7 +1715,7 @@ export class BinaryTree<
cur = cur.right;
}
break;
case 'post':
case 'POST':
while (cur) {
if (cur.left) {
const predecessor = this.getPredecessor(cur);

View file

@ -569,7 +569,7 @@ export class BST<
*/
override dfs<C extends BTNCallback<NODE>>(
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
pattern: DFSOrderPattern = 'IN',
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType: IterationType = 'ITERATIVE'
): ReturnType<C>[] {
@ -756,7 +756,7 @@ export class BST<
* @returns The function `perfectlyBalance` returns a boolean value.
*/
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
const sorted = this.dfs(node => node, 'in'),
const sorted = this.dfs(node => node, 'IN'),
n = sorted.length;
this.clear();
@ -888,6 +888,15 @@ export class BST<
return compared > 0 ? 'GT' : compared < 0 ? 'LT' : 'EQ';
}
/**
* The function `_lt` compares two values `a` and `b` using an extractor function and returns true if
* `a` is less than `b` based on the specified variant.
* @param {K} a - The parameter "a" is of type "K", which means it can be any type. It represents the
* first value to be compared in the function.
* @param {K} b - The parameter `b` is of type `K`, which means it can be any type. It is used as one
* of the arguments for the comparison in the `_lt` function.
* @returns a boolean value.
*/
protected _lt(a: K, b: K): boolean {
const extractedA = this.extractor(a);
const extractedB = this.extractor(b);
@ -897,6 +906,14 @@ export class BST<
// return a < b;
}
/**
* The function compares two values using a custom extractor function and returns true if the first
* value is greater than the second value.
* @param {K} a - The parameter "a" is of type K, which means it can be any type.
* @param {K} b - The parameter "b" is of type K, which means it can be any type. It is used as one
* of the arguments for the comparison in the function.
* @returns a boolean value.
*/
protected _gt(a: K, b: K): boolean {
const extractedA = this.extractor(a);
const extractedB = this.extractor(b);

View file

@ -26,9 +26,9 @@ export class RedBlackTreeNode<
* associated with the key in the Red-Black Tree Node. It is not required and can be omitted when
* creating a new instance of the Red-Black Tree Node.
* @param {RBTNColor} color - The `color` parameter is used to specify the color of the Red-Black
* Tree Node. It is an optional parameter with a default value of `RBTNColor.BLACK`.
* Tree Node. It is an optional parameter with a default value of `'BLACK'`.
*/
constructor(key: K, value?: V, color: RBTNColor = RBTNColor.BLACK) {
constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {
super(key, value);
this._color = color;
}
@ -107,12 +107,12 @@ export class RedBlackTree<
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
* associated with the key in the node. It is not required and can be omitted if not needed.
* @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
* Red-Black Tree. It is an optional parameter with a default value of "RBTNColor.BLACK". The color
* can be either "RBTNColor.RED" or "RBTNColor.BLACK".
* Red-Black Tree. It is an optional parameter with a default value of "'BLACK'". The color
* can be either "'RED'" or "'BLACK'".
* @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
* value, and color.
*/
override createNode(key: K, value?: V, color: RBTNColor = RBTNColor.BLACK): NODE {
override createNode(key: K, value?: V, color: RBTNColor = 'BLACK'): NODE {
return new RedBlackTreeNode<K, V, NODE>(key, value, color) as NODE;
}
@ -157,10 +157,10 @@ export class RedBlackTree<
if (key === undefined || key === null) {
return;
} else {
node = this.createNode(key, value, RBTNColor.RED);
node = this.createNode(key, value, 'RED');
}
} else if (!this.isNode(keyOrNodeOrEntry)) {
node = this.createNode(keyOrNodeOrEntry, value, RBTNColor.RED);
node = this.createNode(keyOrNodeOrEntry, value, 'RED');
} else {
return;
}
@ -282,7 +282,7 @@ export class RedBlackTree<
if (insertStatus === 'CREATED') {
// Ensure the root is black
if (this.isRealNode(this._root)) {
this._root.color = RBTNColor.BLACK;
this._root.color = 'BLACK';
} else {
return false;
}
@ -363,7 +363,7 @@ export class RedBlackTree<
this._size--;
// If the original color was black, fix the tree
if (originalColor === RBTNColor.BLACK) {
if (originalColor === 'BLACK') {
this._deleteFixup(replacementNode);
}
@ -451,7 +451,7 @@ export class RedBlackTree<
node.left = this.SENTINEL;
node.right = this.SENTINEL;
node.color = RBTNColor.RED;
node.color = 'RED';
this._insertFixup(node);
return 'CREATED';
@ -500,16 +500,16 @@ export class RedBlackTree<
*/
protected _insertFixup(z: NODE | undefined): void {
// Continue fixing the tree as long as the parent of z is red
while (z?.parent?.color === RBTNColor.RED) {
while (z?.parent?.color === 'RED') {
// Check if the parent of z is the left child of its parent
if (z.parent === z.parent.parent?.left) {
// Case 1: The uncle (y) of z is red
const y = z.parent.parent.right;
if (y?.color === RBTNColor.RED) {
if (y?.color === 'RED') {
// Set colors to restore properties of Red-Black Tree
z.parent.color = RBTNColor.BLACK;
y.color = RBTNColor.BLACK;
z.parent.parent.color = RBTNColor.RED;
z.parent.color = 'BLACK';
y.color = 'BLACK';
z.parent.parent.color = 'RED';
// Move up the tree to continue fixing
z = z.parent.parent;
} else {
@ -523,8 +523,8 @@ export class RedBlackTree<
// Case 3: The uncle (y) of z is black, and z is a left child
// Adjust colors and perform a right rotation
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
z.parent.color = RBTNColor.BLACK;
z.parent.parent.color = RBTNColor.RED;
z.parent.color = 'BLACK';
z.parent.parent.color = 'RED';
this._rightRotate(z.parent.parent);
}
}
@ -532,10 +532,10 @@ export class RedBlackTree<
// Symmetric case for the right child (left and right exchanged)
// Follow the same logic as above with left and right exchanged
const y: NODE | undefined = z?.parent?.parent?.left;
if (y?.color === RBTNColor.RED) {
z.parent.color = RBTNColor.BLACK;
y.color = RBTNColor.BLACK;
z.parent.parent!.color = RBTNColor.RED;
if (y?.color === 'RED') {
z.parent.color = 'BLACK';
y.color = 'BLACK';
z.parent.parent!.color = 'RED';
z = z.parent.parent;
} else {
if (z === z.parent.left) {
@ -544,8 +544,8 @@ export class RedBlackTree<
}
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
z.parent.color = RBTNColor.BLACK;
z.parent.parent.color = RBTNColor.RED;
z.parent.color = 'BLACK';
z.parent.parent.color = 'RED';
this._leftRotate(z.parent.parent);
}
}
@ -553,7 +553,7 @@ export class RedBlackTree<
}
// Ensure that the root is black after fixing
if (this.isRealNode(this._root)) this._root.color = RBTNColor.BLACK;
if (this.isRealNode(this._root)) this._root.color = 'BLACK';
}
/**
@ -573,14 +573,14 @@ export class RedBlackTree<
*/
protected _deleteFixup(node: NODE | undefined): void {
// Early exit condition
if (!node || node === this.root || node.color === RBTNColor.BLACK) {
if (!node || node === this.root || node.color === 'BLACK') {
if (node) {
node.color = RBTNColor.BLACK; // Ensure the final node is black
node.color = 'BLACK'; // Ensure the final node is black
}
return;
}
while (node && node !== this.root && node.color === RBTNColor.BLACK) {
while (node && node !== this.root && node.color === 'BLACK') {
const parent: NODE | undefined = node.parent;
if (!parent) {
@ -591,22 +591,22 @@ export class RedBlackTree<
let sibling = parent.right;
// Cases 1 and 2: Sibling is red or both children of sibling are black
if (sibling?.color === RBTNColor.RED) {
sibling.color = RBTNColor.BLACK;
parent.color = RBTNColor.RED;
if (sibling?.color === 'RED') {
sibling.color = 'BLACK';
parent.color = 'RED';
this._leftRotate(parent);
sibling = parent.right;
}
// Case 3: Sibling's left child is black
if ((sibling?.left?.color ?? RBTNColor.BLACK) === RBTNColor.BLACK) {
if (sibling) sibling.color = RBTNColor.RED;
if ((sibling?.left?.color ?? 'BLACK') === 'BLACK') {
if (sibling) sibling.color = 'RED';
node = parent;
} else {
// Case 4: Adjust colors and perform a right rotation
if (sibling?.left) sibling.left.color = RBTNColor.BLACK;
if (sibling?.left) sibling.left.color = 'BLACK';
if (sibling) sibling.color = parent.color;
parent.color = RBTNColor.BLACK;
parent.color = 'BLACK';
this._rightRotate(parent);
node = this.root;
}
@ -615,22 +615,22 @@ export class RedBlackTree<
let sibling = parent.left;
// Cases 1 and 2: Sibling is red or both children of sibling are black
if (sibling?.color === RBTNColor.RED) {
sibling.color = RBTNColor.BLACK;
if (parent) parent.color = RBTNColor.RED;
if (sibling?.color === 'RED') {
sibling.color = 'BLACK';
if (parent) parent.color = 'RED';
this._rightRotate(parent);
if (parent) sibling = parent.left;
}
// Case 3: Sibling's left child is black
if ((sibling?.right?.color ?? RBTNColor.BLACK) === RBTNColor.BLACK) {
if (sibling) sibling.color = RBTNColor.RED;
if ((sibling?.right?.color ?? 'BLACK') === 'BLACK') {
if (sibling) sibling.color = 'RED';
node = parent;
} else {
// Case 4: Adjust colors and perform a left rotation
if (sibling?.right) sibling.right.color = RBTNColor.BLACK;
if (sibling?.right) sibling.right.color = 'BLACK';
if (sibling) sibling.color = parent.color;
if (parent) parent.color = RBTNColor.BLACK;
if (parent) parent.color = 'BLACK';
this._leftRotate(parent);
node = this.root;
}
@ -639,7 +639,7 @@ export class RedBlackTree<
// Ensure that the final node (possibly the root) is black
if (node) {
node.color = RBTNColor.BLACK;
node.color = 'BLACK';
}
}

View file

@ -25,17 +25,19 @@ export class TreeMultiMapNode<
NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNodeNested<K, V>
> extends RedBlackTreeNode<K, V, NODE> {
/**
* The constructor function initializes an instance of a class with a key, value, and count.
* @param {K} key - The key parameter is of type K, which represents the type of the key for the
* constructor. It is required and must be provided when creating an instance of the class.
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the
* value associated with the key in the constructor. If no value is provided, it will be `undefined`.
* @param [count=1] - The "count" parameter is an optional parameter that specifies the number of
* times the key-value pair should be repeated. If no value is provided for "count", it defaults to
* 1.
* The constructor function initializes a Red-Black Tree node with a key, value, count, and color.
* @param {K} key - The key parameter represents the key of the node in the Red-Black Tree. It is
* used to identify and locate the node within the tree.
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
* associated with the key in the Red-Black Tree node. It is not required and can be omitted when
* creating a new node.
* @param [count=1] - The `count` parameter represents the number of occurrences of a particular key
* in the Red-Black Tree. It is an optional parameter with a default value of 1.
* @param {RBTNColor} [color=BLACK] - The `color` parameter is used to specify the color of the node
* in a Red-Black Tree. It is optional and has a default value of `'BLACK'`.
*/
constructor(key: K, value?: V, count = 1) {
super(key, value);
constructor(key: K, value?: V, count = 1, color: RBTNColor = 'BLACK') {
super(key, value, color);
this.count = count;
}
@ -92,25 +94,41 @@ export class TreeMultiMap<
return this._count;
}
getMutableCount(): number {
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*/
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
*
* The function calculates the sum of the count property of all nodes in a tree using depth-first
* search.
* @returns the sum of the count property of all nodes in the tree.
*/
getComputedCount(): number {
let sum = 0;
this.dfs(node => (sum += node.count));
return sum;
}
/**
* The function creates a new TreeMultiMapNode object with the specified key, value, and count.
* The function creates a new TreeMultiMapNode with the specified key, value, color, and count.
* @param {K} key - The key parameter represents the key of the node being created. It is of type K,
* which is a generic type that can be replaced with any specific type when using the function.
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
* associated with the key in the node. It is of type `V`, which can be any data type.
* @param {number} [count] - The `count` parameter represents the number of occurrences of a
* key-value pair in the TreeMultiMap. It is an optional parameter, so if it is not provided, it will
* default to 1.
* @returns a new instance of the TreeMultiMapNode class, casted as NODE.
* which is a generic type representing the key type of the node.
* @param {V} [value] - The `value` parameter represents the value associated with the key in the
* node. It is an optional parameter, which means it can be omitted when calling the `createNode`
* function. If provided, it should be of type `V`.
* @param {RBTNColor} [color=BLACK] - The color parameter is used to specify the color of the node in
* a Red-Black Tree. It can have two possible values: 'RED' or 'BLACK'. The default value is 'BLACK'.
* @param {number} [count] - The `count` parameter represents the number of occurrences of a key in
* the tree. It is an optional parameter and is used to keep track of the number of values associated
* with a key in the tree.
* @returns A new instance of the TreeMultiMapNode class is being returned.
*/
override createNode(key: K, value?: V, count?: number): NODE {
return new TreeMultiMapNode(key, value, count) as NODE;
override createNode(key: K, value?: V, color: RBTNColor = 'BLACK', count?: number): NODE {
return new TreeMultiMapNode(key, value, count, color) as NODE;
}
/**
@ -154,10 +172,10 @@ export class TreeMultiMap<
if (key === undefined || key === null) {
return;
} else {
node = this.createNode(key, value, count);
node = this.createNode(key, value, 'BLACK', count);
}
} else if (!this.isNode(keyOrNodeOrEntry)) {
node = this.createNode(keyOrNodeOrEntry, value, count);
node = this.createNode(keyOrNodeOrEntry, value, 'BLACK', count);
} else {
return;
}
@ -315,7 +333,7 @@ export class TreeMultiMap<
this._size--;
// If the original color was black, fix the tree
if (originalColor === RBTNColor.BLACK) {
if (originalColor === 'BLACK') {
this._deleteFixup(replacementNode);
}
@ -358,7 +376,7 @@ export class TreeMultiMap<
* @returns a boolean value.
*/
override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
const sorted = this.dfs(node => node, 'in'),
const sorted = this.dfs(node => node, 'IN'),
n = sorted.length;
if (sorted.length < 1) return false;
@ -432,7 +450,7 @@ export class TreeMultiMap<
destNode = this.ensureNode(destNode);
if (srcNode && destNode) {
const { key, value, count, color } = destNode;
const tempNode = this.createNode(key, value, count);
const tempNode = this.createNode(key, value, color, count);
if (tempNode) {
tempNode.color = color;

View file

@ -247,10 +247,10 @@ export class Heap<E = any> extends IterableElementBase<E> {
* Space Complexity: O(log n)
*
* Depth-first search (DFS) method, different traversal orders can be selected
* @param order - Traverse order parameter: 'in' (in-order), 'pre' (pre-order) or 'post' (post-order).
* @param order - Traverse order parameter: 'IN' (in-order), 'PRE' (pre-order) or 'POST' (post-order).
* @returns An array containing elements traversed in the specified order.
*/
dfs(order: DFSOrderPattern = 'pre'): E[] {
dfs(order: DFSOrderPattern = 'PRE'): E[] {
const result: E[] = [];
// Auxiliary recursive function, traverses the binary heap according to the traversal order
@ -258,15 +258,15 @@ export class Heap<E = any> extends IterableElementBase<E> {
const left = 2 * index + 1,
right = left + 1;
if (index < this.size) {
if (order === 'in') {
if (order === 'IN') {
_dfs(left);
result.push(this.elements[index]);
_dfs(right);
} else if (order === 'pre') {
} else if (order === 'PRE') {
result.push(this.elements[index]);
_dfs(left);
_dfs(right);
} else if (order === 'post') {
} else if (order === 'POST') {
_dfs(left);
_dfs(right);
result.push(this.elements[index]);

View file

@ -13,7 +13,7 @@ export type FamilyPosition = 'ROOT' | 'LEFT' | 'RIGHT' | 'ROOT_LEFT' | 'ROOT_RIG
export type Comparator<K> = (a: K, b: K) => number;
export type DFSOrderPattern = 'pre' | 'in' | 'post';
export type DFSOrderPattern = 'PRE' | 'IN' | 'POST';
export type NodeDisplayLayout = [string[], number, number, number];

View file

@ -1,9 +1,7 @@
import { RedBlackTree, RedBlackTreeNode } from '../../../data-structures';
import type { BSTOptions } from "./bst";
export enum RBTNColor { RED = 1, BLACK = 0}
// export type RBTNColor = 'RED' | 'BLACK';
export type RBTNColor = 'RED' | 'BLACK';
export type RedBlackTreeNodeNested<K, V> = RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

View file

@ -23,7 +23,7 @@ describe('AVL Tree Test from data-structure-typed', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -33,7 +33,7 @@ describe('AVL Tree Test from data-structure-typed', () => {
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(node15?.value).toBe(15);
const dfs = tree.dfs(node => node, 'in');
const dfs = tree.dfs(node => node, 'IN');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);

View file

@ -40,7 +40,7 @@ describe('AVL Tree Test', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'in', 15);
node15 && tree.dfs(node => (subTreeSum += node.key), 'IN', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -50,7 +50,7 @@ describe('AVL Tree Test', () => {
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(node15?.value).toBe(15);
const dfs = tree.dfs(node => node, 'in');
const dfs = tree.dfs(node => node, 'IN');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);

View file

@ -34,7 +34,7 @@ describe('Individual package BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'in', 15);
node15 && bst.dfs(node => (subTreeSum += node.key), 'IN', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -46,7 +46,7 @@ describe('Individual package BST operations test', () => {
const node11 = bst.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = bst.dfs(node => node, 'in');
const dfsInorderNodes = bst.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
@ -231,7 +231,7 @@ describe('Individual package BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'in', node15);
node15 && objBST.dfs(node => (subTreeSum += node.key), 'IN', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -243,7 +243,7 @@ describe('Individual package BST operations test', () => {
const node11 = objBST.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = objBST.dfs(node => node, 'in');
const dfsInorderNodes = objBST.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);

View file

@ -34,7 +34,7 @@ suite
for (let i = 0; i < THOUSAND; i++) biTree.bfs();
})
.add(`${THOUSAND.toLocaleString()} morris`, () => {
for (let i = 0; i < THOUSAND; i++) biTree.morris(n => n, 'pre');
for (let i = 0; i < THOUSAND; i++) biTree.morris(n => n, 'PRE');
});
// export { suite };

View file

@ -31,7 +31,7 @@ describe('AVLTreeMultiMap count', () => {
tm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 1);
tm.delete(2);
expect(tm.count).toBe(12);
expect(tm.getMutableCount()).toBe(16);
expect(tm.getComputedCount()).toBe(16);
});
});
@ -91,7 +91,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(minNodeBySpecificNode?.key).toBe(15);
let subTreeSum = 0;
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
@ -99,7 +99,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(node15 instanceof AVLTreeMultiMapNode);
if (node15 instanceof AVLTreeMultiMapNode) {
const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'pre', 15);
const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'PRE', 15);
expect(subTreeAdd);
}
const node11 = treeMultimap.getNode(11);
@ -109,7 +109,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = treeMultimap.dfs(node => node, 'in');
const dfsInorderNodes = treeMultimap.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
expect(treeMultimap.isPerfectlyBalanced()).toBe(false);
@ -345,7 +345,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(minNodeBySpecificNode?.key).toBe(15);
let subTreeSum = 0;
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
@ -353,7 +353,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(node15 instanceof AVLTreeMultiMapNode);
if (node15 instanceof AVLTreeMultiMapNode) {
const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'pre', 15);
const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'PRE', 15);
expect(subTreeAdd);
}
const node11 = treeMultimap.getNode(11);
@ -363,7 +363,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = treeMultimap.dfs(node => node, 'in');
const dfsInorderNodes = treeMultimap.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
expect(treeMultimap.isPerfectlyBalanced()).toBe(true);

View file

@ -24,7 +24,7 @@ describe('AVL Tree Test', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'pre', node15);
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -34,7 +34,7 @@ describe('AVL Tree Test', () => {
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(node15?.value).toBe(15);
const dfs = tree.dfs(node => node, 'in');
const dfs = tree.dfs(node => node, 'IN');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);
tree.perfectlyBalance();
@ -132,7 +132,7 @@ describe('AVL Tree Test recursively', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'pre', node15);
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -142,7 +142,7 @@ describe('AVL Tree Test recursively', () => {
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(node15?.value).toBe(15);
const dfs = tree.dfs(node => node, 'in');
const dfs = tree.dfs(node => node, 'IN');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);

View file

@ -171,20 +171,20 @@ describe('BinaryTree', () => {
expect(cloned.root?.right?.key).toBe(6);
expect(cloned.root?.right?.left?.key).toBe(3);
expect(cloned.root?.right?.right).toBe(null);
expect(cloned.dfs(node => node.key, 'pre', cloned.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
expect(cloned.dfs(node => node.key, 'PRE', cloned.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(cloned.dfs(node => (node ? node.key : null), 'PRE', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(cloned.dfs(node => (node ? node.key : node), 'pre', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
expect(cloned.dfs(node => (node ? node.key : node), 'PRE', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), 'RECURSIVE', true)).toEqual([
expect(cloned.dfs(node => (node ? node.key : null), 'PRE', cloned.getNode(6), 'RECURSIVE', true)).toEqual([
6,
3,
7,
@ -294,22 +294,22 @@ describe('BinaryTree', () => {
it('should sub tree traverse', () => {
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'ITERATIVE', false)).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'RECURSIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), 'ITERATIVE', true)).toEqual([
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE', false)).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'RECURSIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(tree.dfs(node => (node ? node.key : node), 'pre', tree.getNode(6), 'ITERATIVE', true)).toEqual([
expect(tree.dfs(node => (node ? node.key : node), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), 'RECURSIVE', true)).toEqual([
expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', true)).toEqual([
6,
3,
7,
@ -362,36 +362,36 @@ describe('BinaryTree Morris Traversal', () => {
tree.add(5);
it('should perform in-order Morris traversal correctly as dfs traversal', () => {
// Perform in-order Morris traversal
const result = tree.morris(node => node.key, 'in');
const result = tree.morris(node => node.key, 'IN');
// Expected in-order traversal result
const expected = [4, 2, 5, 1, 3];
expect(result).toEqual(expected);
expect(tree.dfs(node => node.key, 'in')).toEqual(expected);
expect(tree.dfs(node => node.key, 'in', tree.root, 'RECURSIVE')).toEqual(expected);
expect(tree.dfs(node => node.key, 'IN')).toEqual(expected);
expect(tree.dfs(node => node.key, 'IN', tree.root, 'RECURSIVE')).toEqual(expected);
});
it('should perform pre-order Morris traversal correctly as dfs traversal', () => {
// Perform pre-order Morris traversal
const result = tree.morris(node => node.key, 'pre');
const result = tree.morris(node => node.key, 'PRE');
// Expected pre-order traversal result
const expected = [1, 2, 4, 5, 3];
expect(result).toEqual(expected);
expect(tree.dfs(node => node.key, 'pre')).toEqual(expected);
expect(tree.dfs(node => node.key, 'PRE')).toEqual(expected);
});
it('should perform post-order Morris traversal correctly as dfs traversal', () => {
// Perform post-order Morris traversal
const result = tree.morris(node => node.key, 'post');
const result = tree.morris(node => node.key, 'POST');
// Expected post-order traversal result
const expected = [4, 5, 2, 3, 1];
expect(result).toEqual([4, 5, 2, 3, 1]);
expect(tree.dfs(node => node.key, 'post')).toEqual(expected);
expect(tree.dfs(node => node.key, 'POST')).toEqual(expected);
});
it('after morris traversals should the structure of the tree be correct', () => {
@ -445,11 +445,11 @@ describe('BinaryTree traversals', () => {
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
expect(tree.dfs(node => node.key, 'pre')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'pre', tree.root, 'RECURSIVE')).toEqual([
expect(tree.dfs(node => node.key, 'PRE')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'PRE', tree.root, 'RECURSIVE')).toEqual([
35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55
]);
expect(tree.dfs(node => node, 'pre', tree.root, 'ITERATIVE', true).map(node => (node ? node.key : null))).toEqual([
expect(tree.dfs(node => node, 'PRE', tree.root, 'ITERATIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
15,
@ -464,7 +464,7 @@ describe('BinaryTree traversals', () => {
45,
55
]);
expect(tree.dfs(node => node, 'pre', tree.root, 'RECURSIVE', true).map(node => (node ? node.key : null))).toEqual([
expect(tree.dfs(node => node, 'PRE', tree.root, 'RECURSIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
15,
@ -480,9 +480,9 @@ describe('BinaryTree traversals', () => {
55
]);
expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
expect(tree.dfs(node => node.key, 'post')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
expect(tree.dfs(node => node.key, 'post', tree.root, 'RECURSIVE')).toEqual([
expect(tree.dfs(node => node.key, 'IN')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
expect(tree.dfs(node => node.key, 'POST')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
expect(tree.dfs(node => node.key, 'POST', tree.root, 'RECURSIVE')).toEqual([
16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35
]);
expect(tree.bfs(node => node.key, tree.root, 'RECURSIVE')).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);

View file

@ -54,7 +54,7 @@ describe('BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -66,7 +66,7 @@ describe('BST operations test', () => {
const node11 = bst.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = bst.dfs(node => node, 'in');
const dfsInorderNodes = bst.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
@ -257,7 +257,7 @@ describe('BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'pre', node15);
node15 && objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -269,7 +269,7 @@ describe('BST operations test', () => {
const node11 = objBST.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = objBST.dfs(node => node, 'in');
const dfsInorderNodes = objBST.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
@ -444,7 +444,7 @@ describe('BST operations test recursively', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -456,7 +456,7 @@ describe('BST operations test recursively', () => {
const node11 = bst.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = bst.dfs(node => node, 'in');
const dfsInorderNodes = bst.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
@ -645,7 +645,7 @@ describe('BST operations test recursively', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'pre', node15);
node15 && objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -657,7 +657,7 @@ describe('BST operations test recursively', () => {
const node11 = objBST.getNode(11);
expect(node11).toBeInstanceOf(BSTNode);
const dfsInorderNodes = objBST.dfs(node => node, 'in');
const dfsInorderNodes = objBST.dfs(node => node, 'IN');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
@ -932,10 +932,10 @@ describe('BST Performance test', function () {
it('should dfs as sub tree traversal, null should be ignored', () => {
const bst = new BST();
bst.addMany([4, 2, 6, 1, 3, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'PRE', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'PRE', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'PRE', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'PRE', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
});
});

View file

@ -1,4 +1,4 @@
import { BinaryTreeNode, BSTNode, RBTNColor, RedBlackTree, RedBlackTreeNode } from '../../../../src';
import { BinaryTreeNode, BSTNode, RedBlackTree, RedBlackTreeNode } from '../../../../src';
import { getRandomInt, getRandomIntArray, magnitude } from '../../../utils';
import { OrderedMap } from 'js-sdsl';
@ -263,42 +263,42 @@ describe('RedBlackTree 2', () => {
let node6F = rbTree.getNode(6);
let node2F = rbTree.getNode(2);
expect(node10F?.key).toBe(10);
expect(node10F?.color).toBe(RBTNColor.BLACK);
expect(node10F?.color).toBe('BLACK');
expect(node10F?.left).toBe(node5F);
expect(node10F?.right).toBe(node20F);
expect(node10F?.parent).toBe(undefined);
expect(node20F?.key).toBe(20);
expect(node20F?.color).toBe(RBTNColor.BLACK);
expect(node20F?.color).toBe('BLACK');
expect(node20F?.left).toBe(node15F);
expect(node20F?.right).toBe(node21F);
expect(node20F?.parent).toBe(node10F);
expect(node5F?.key).toBe(5);
expect(node5F?.color).toBe(RBTNColor.BLACK);
expect(node5F?.color).toBe('BLACK');
expect(node5F?.left).toBe(node2F);
expect(node5F?.right).toBe(node6F);
expect(node5F?.parent).toBe(node10F);
expect(node15F?.key).toBe(15);
expect(node15F?.color).toBe(RBTNColor.RED);
expect(node15F?.color).toBe('RED');
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?.color).toBe('RED');
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?.color).toBe('RED');
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?.color).toBe('RED');
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?.color).toBe('RED');
expect(node15F?.left).toBe(rbTree.SENTINEL);
expect(node15F?.right).toBe(rbTree.SENTINEL);
expect(node15F?.parent).toBe(node20F);
@ -311,38 +311,38 @@ describe('RedBlackTree 2', () => {
node6F = rbTree.getNode(6);
node2F = rbTree.getNode(2);
expect(node10F?.key).toBe(10);
expect(node10F?.color).toBe(RBTNColor.BLACK);
expect(node10F?.color).toBe('BLACK');
expect(node10F?.left).toBe(node6F);
expect(node10F?.right).toBe(node20F);
expect(node10F?.parent).toBe(undefined);
expect(node20F?.key).toBe(20);
expect(node20F?.color).toBe(RBTNColor.BLACK);
expect(node20F?.color).toBe('BLACK');
expect(node20F?.left).toBe(node15F);
expect(node20F?.right).toBe(node21F);
expect(node20F?.parent).toBe(node10F);
expect(node5F).toBe(undefined);
expect(node15F?.key).toBe(15);
expect(node15F?.color).toBe(RBTNColor.RED);
expect(node15F?.color).toBe('RED');
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?.color).toBe('RED');
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?.color).toBe('BLACK');
expect(node6F?.left).toBe(node2F);
expect(node6F?.right).toBe(rbTree.SENTINEL);
expect(node6F?.parent).toBe(node10F);
expect(node2F?.key).toBe(2);
expect(node2F?.color).toBe(RBTNColor.RED);
expect(node2F?.color).toBe('RED');
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?.color).toBe('RED');
expect(node15F?.left).toBe(rbTree.SENTINEL);
expect(node15F?.right).toBe(rbTree.SENTINEL);
expect(node15F?.parent).toBe(node20F);
@ -355,34 +355,34 @@ describe('RedBlackTree 2', () => {
node6F = rbTree.getNode(6);
node2F = rbTree.getNode(2);
expect(node10F?.key).toBe(10);
expect(node10F?.color).toBe(RBTNColor.BLACK);
expect(node10F?.color).toBe('BLACK');
expect(node10F?.left).toBe(node6F);
expect(node10F?.right).toBe(node21F);
expect(node10F?.parent).toBe(undefined);
expect(node20F).toBe(undefined);
expect(node5F).toBe(undefined);
expect(node15F?.key).toBe(15);
expect(node15F?.color).toBe(RBTNColor.RED);
expect(node15F?.color).toBe('RED');
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?.color).toBe('BLACK');
expect(node21F?.left).toBe(node15F);
expect(node21F?.right).toBe(rbTree.SENTINEL);
expect(node21F?.parent).toBe(node10F);
expect(node6F?.key).toBe(6);
expect(node6F?.color).toBe(RBTNColor.BLACK);
expect(node6F?.color).toBe('BLACK');
expect(node6F?.left).toBe(node2F);
expect(node6F?.right).toBe(rbTree.SENTINEL);
expect(node6F?.parent).toBe(node10F);
expect(node2F?.key).toBe(2);
expect(node2F?.color).toBe(RBTNColor.RED);
expect(node2F?.color).toBe('RED');
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?.color).toBe('RED');
expect(node15F?.left).toBe(rbTree.SENTINEL);
expect(node15F?.right).toBe(rbTree.SENTINEL);
expect(node15F?.parent).toBe(node21F);
@ -484,11 +484,11 @@ describe('RedBlackTree 2', () => {
expect(rbTree.isBST()).toBe(true);
expect(rbTree.isBST(rbTree.root, 'RECURSIVE')).toBe(true);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, 'ITERATIVE')).toEqual([
expect(rbTree.dfs(n => n.key, 'IN', rbTree.root, '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(rbTree.dfs(n => n.key, 'in', rbTree.root, 'RECURSIVE')).toEqual([
expect(rbTree.dfs(n => n.key, 'IN', rbTree.root, '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
]);
@ -504,7 +504,7 @@ describe('RedBlackTree 2', () => {
expect(rbTree.size).toBe(0);
expect(rbTree.isBST()).toBe(true);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, 'ITERATIVE')).toEqual([]);
expect(rbTree.dfs(n => n.key, 'IN', rbTree.root, 'ITERATIVE')).toEqual([]);
rbTree.clear();
for (let i = 0; i < 1000; i++) {

View file

@ -22,7 +22,7 @@ describe('TreeMultiMap count', () => {
const newNode = new TreeMultiMapNode(3, 33, 10);
tmm.add(newNode);
expect(tmm.count).toBe(15);
expect(tmm.getMutableCount()).toBe(15);
expect(tmm.getComputedCount()).toBe(15);
expect(tmm.getNode(3)?.count).toBe(11);
});
@ -33,7 +33,7 @@ describe('TreeMultiMap count', () => {
[3, 3]
]);
tmm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 1);
expect(tmm.getMutableCount()).toBe(7);
expect(tmm.getComputedCount()).toBe(7);
expect(tmm.count).toBe(3);
});
});
@ -57,7 +57,7 @@ describe('TreeMultiMap operations test1', () => {
tmm.add([11, 11]);
tmm.add([3, 3]);
expect(tmm.count).toBe(2);
expect(tmm.getMutableCount()).toBe(2);
expect(tmm.getComputedCount()).toBe(2);
expect(tmm.size).toBe(2);
const keyValuePairs: [number, number][] = [
@ -82,13 +82,13 @@ describe('TreeMultiMap operations test1', () => {
tmm.addMany(keyValuePairs);
expect(tmm.size).toBe(16);
expect(tmm.count).toBe(18);
expect(tmm.getMutableCount()).toBe(18);
expect(tmm.getComputedCount()).toBe(18);
tmm.delete(11);
expect(tmm.count).toBe(17);
expect(tmm.getMutableCount()).toBe(17);
expect(tmm.getComputedCount()).toBe(17);
tmm.delete(3, undefined, true);
expect(tmm.count).toBe(15);
expect(tmm.getMutableCount()).toBe(15);
expect(tmm.getComputedCount()).toBe(15);
});
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
@ -123,7 +123,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.size).toBe(16);
expect(tmm.count).toBe(18);
expect(tmm.getMutableCount()).toBe(18);
expect(tmm.getComputedCount()).toBe(18);
expect(tmm.has(6));
isDebug && tmm.print();
@ -148,7 +148,7 @@ describe('TreeMultiMap operations test1', () => {
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && tmm.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
tmm.lesserOrGreaterTraverse((node: TreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
@ -156,7 +156,7 @@ describe('TreeMultiMap operations test1', () => {
expect(node15 instanceof TreeMultiMapNode);
if (node15 instanceof TreeMultiMapNode) {
const subTreeAdd = tmm.dfs(node => (node.count += 1), 'pre', 15);
const subTreeAdd = tmm.dfs(node => (node.count += 1), 'PRE', 15);
expect(subTreeAdd);
}
const node11 = tmm.getNode(11);
@ -166,7 +166,7 @@ describe('TreeMultiMap operations test1', () => {
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = tmm.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);
@ -309,7 +309,7 @@ describe('TreeMultiMap operations test1', () => {
expect(bfsNodes[2].key).toBe(16);
expect(tmm.count).toBe(6);
expect(tmm.getMutableCount()).toBe(8);
expect(tmm.getComputedCount()).toBe(8);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
@ -341,7 +341,7 @@ describe('TreeMultiMap operations test1', () => {
if (objTreeMultiMap.root) expect(objTreeMultiMap.root.key).toBe(5);
expect(objTreeMultiMap.count).toBe(16);
expect(objTreeMultiMap.getMutableCount()).toBe(16);
expect(objTreeMultiMap.getComputedCount()).toBe(16);
expect(objTreeMultiMap.has(6)).toBe(true);
});
@ -379,7 +379,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.size).toBe(16);
expect(tmm.count).toBe(18);
expect(tmm.getMutableCount()).toBe(18);
expect(tmm.getComputedCount()).toBe(18);
expect(tmm.has(6));
@ -404,7 +404,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && tmm.dfs(node => (subTreeSum += node.key), 'pre', 15);
node15 && tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
expect(tmm.has(9)).toBe(true);
@ -420,7 +420,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(node15 instanceof TreeMultiMapNode);
if (node15 instanceof TreeMultiMapNode) {
const subTreeAdd = tmm.dfs(node => (node.count += 1), 'pre', 15);
const subTreeAdd = tmm.dfs(node => (node.count += 1), 'PRE', 15);
expect(subTreeAdd);
}
const node11 = tmm.getNode(11);
@ -430,7 +430,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = tmm.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);
@ -574,7 +574,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(bfsNodes[2].key).toBe(16);
expect(tmm.count).toBe(6);
expect(tmm.getMutableCount()).toBe(8);
expect(tmm.getComputedCount()).toBe(8);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
@ -606,7 +606,7 @@ describe('TreeMultiMap operations test recursively1', () => {
if (objTreeMultiMap.root) expect(objTreeMultiMap.root.key).toBe(5);
expect(objTreeMultiMap.count).toBe(16);
expect(objTreeMultiMap.getMutableCount()).toBe(16);
expect(objTreeMultiMap.getComputedCount()).toBe(16);
expect(objTreeMultiMap.has(6)).toBe(true);
});
@ -811,7 +811,7 @@ describe('TreeMultiMap iterative methods test', () => {
test('should clone work well', () => {
expect(treeMM.count).toBe(21);
expect(treeMM.getMutableCount()).toBe(21);
expect(treeMM.getComputedCount()).toBe(21);
const cloned = treeMM.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.root?.right?.value).toBe('c');

View file

@ -42,9 +42,9 @@ describe('PriorityQueue Operation Test', () => {
const clonedPriorityQueue = minPQ1.clone();
expect(clonedPriorityQueue.elements).toEqual(minPQ1.elements);
expect(clonedPriorityQueue.sort()).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
expect(minPQ1.dfs('in')).toEqual([4, 3, 2, 5, 1, 8, 6, 7]);
expect(minPQ1.dfs('post')).toEqual([4, 3, 5, 2, 8, 7, 6, 1]);
expect(minPQ1.dfs('pre')).toEqual([1, 2, 3, 4, 5, 6, 8, 7]);
expect(minPQ1.dfs('IN')).toEqual([4, 3, 2, 5, 1, 8, 6, 7]);
expect(minPQ1.dfs('POST')).toEqual([4, 3, 5, 2, 8, 7, 6, 1]);
expect(minPQ1.dfs('PRE')).toEqual([1, 2, 3, 4, 5, 6, 8, 7]);
});
});