diff --git a/package-lock.json b/package-lock.json index 09e9f01..3257bd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,17 +15,17 @@ "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", "auto-changelog": "^2.4.0", - "avl-tree-typed": "^1.40.0", + "avl-tree-typed": "^1.41.0", "benchmark": "^2.1.4", - "binary-tree-typed": "^1.40.0", - "bst-typed": "^1.40.0", + "binary-tree-typed": "^1.41.0", + "bst-typed": "^1.41.0", "dependency-cruiser": "^14.1.0", "eslint": "^8.50.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.28.1", - "heap-typed": "^1.40.0", + "heap-typed": "^1.41.0", "istanbul-badges-readme": "^1.8.5", "jest": "^29.7.0", "prettier": "^3.0.3", @@ -2728,12 +2728,12 @@ } }, "node_modules/avl-tree-typed": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.40.0.tgz", - "integrity": "sha512-Nw2sLCkPmXQWZRJXhQ6BacyWNdX199sjifhdZUOJPLyq9ha+gFzyq2yQCG3+7QrMRCo9JsPIXXSw8PPKPAK2CA==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.41.0.tgz", + "integrity": "sha512-fY0TV30CtWSqLUFeT4fiyrYNSiwXjHL5hObSTE8D8ngWxLsL4QPGVL5lA3VXAPiul3BRJK22s9klVc4YZgdgYQ==", "dev": true, "dependencies": { - "data-structure-typed": "^1.40.0" + "data-structure-typed": "^1.41.0" } }, "node_modules/babel-jest": { @@ -2927,12 +2927,12 @@ } }, "node_modules/binary-tree-typed": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.40.0.tgz", - "integrity": "sha512-j459EByswkZFuN4bte7PV8cwwtOFB+37Zwsh2gQJ4k+He/9wSpURaZDXebB4Z4l2Lu+BM/gt4542DEwEykaGaQ==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.41.0.tgz", + "integrity": "sha512-oNHXYVGP2k+qqs1CKt7MFL9araGeFgBhUwIwaE0mj2eHKn2iitirpwt2Umo6j0xXbe2HT685T2POsN8BurXAJw==", "dev": true, "dependencies": { - "data-structure-typed": "^1.40.0" + "data-structure-typed": "^1.41.0" } }, "node_modules/brace-expansion": { @@ -3011,12 +3011,12 @@ } }, "node_modules/bst-typed": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.40.0.tgz", - "integrity": "sha512-PxM2LtwQOyhytsjtE4dN7XN6GfFHiUfs++jdHVSpkGOqDFNWBM3CYar/nlTjUsTIKzBSSt7BfSIBwo1Lejhwhw==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.41.0.tgz", + "integrity": "sha512-H/MOPuXC53SMo4KleIYFstc3a/GLDVVXShSTG9qrHN2QavZOeg6qyfpkvzOTRyCYjcNlPqMXiwPUtXSaLwH1WA==", "dev": true, "dependencies": { - "data-structure-typed": "^1.40.0" + "data-structure-typed": "^1.41.0" } }, "node_modules/buffer-from": { @@ -3413,9 +3413,9 @@ } }, "node_modules/data-structure-typed": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.40.0.tgz", - "integrity": "sha512-QW3lgqczAA5pKcjfxVH3+kFUi7vKRbOGcPTuFuhGK756E01GiEcl0WJGf0AXCXmTLbqjvLWGKT7K0qFR9RDPgw==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.41.0.tgz", + "integrity": "sha512-f122SHhf5c0CscW9TFpRmwxQeSemnvAvDG0ZbihA0MDkzTozox47iN3lt2CwjEmWvx73WwOABb1JvmiUZI07og==", "dev": true }, "node_modules/debug": { @@ -4771,12 +4771,12 @@ } }, "node_modules/heap-typed": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.40.0.tgz", - "integrity": "sha512-wEdbSCeI3DpHtCNU4rboi6AEZfxRt1CHRAKG6wtA1+X3aX4IyrGC7lugH06ltrNa0kjZF98r2YFSirFzhWFpkA==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.41.0.tgz", + "integrity": "sha512-ZhEqBuu+T4Vkd0K1xZRNpXWVvF/Uy+bYocZo2ZkgnPJ3gGtqBLmoE7MXEPtZxgH6dfrybVvtBLhAsCIqpjp2Lw==", "dev": true, "dependencies": { - "data-structure-typed": "^1.40.0" + "data-structure-typed": "^1.41.0" } }, "node_modules/html-escaper": { diff --git a/package.json b/package.json index 8099676..766e482 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "data-structure-typed", - "version": "1.41.0", + "version": "1.41.1", "description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.", "main": "dist/cjs/index.js", "module": "dist/mjs/index.js", @@ -26,16 +26,16 @@ "format:src": "prettier --write 'src/**/*.{js,ts}'", "format:test": "prettier --write 'test/**/*.{js,ts}'", "format": "npm run format:src && npm run format:test", - "fix:src": "npm run lint:src && npm run format:src", - "fix:test": "npm run lint:test && npm run format:test", - "fix": "npm run fix:src && npm run fix:test", + "reformat:src": "npm run lint:src && npm run format:src", + "reformat:test": "npm run lint:test && npm run format:test", + "reformat": "npm run reformat:src && npm run reformat:test", "update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed --save-dev", "install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multiset-typed trie-typed undirected-graph-typed queue-typed --save-dev", "test": "jest", "check:deps": "dependency-cruiser src", "changelog": "auto-changelog", "coverage:badge": "istanbul-badges-readme", - "ci": "env && git fetch --tags && npm run lint && npm run build && npm run update:subs && npm run test && npm run changelog", + "ci": "env && git fetch --tags && npm run check && npm run lint && npm run build && npm run update:subs && npm run test && npm run changelog", "copy:to-subs": "sh scripts/copy_to_all_subs.sh", "publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh", "publish:docs": "sh scripts/publish_docs.sh", @@ -61,17 +61,17 @@ "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", "auto-changelog": "^2.4.0", - "avl-tree-typed": "^1.40.0", + "avl-tree-typed": "^1.41.0", "benchmark": "^2.1.4", - "binary-tree-typed": "^1.40.0", - "bst-typed": "^1.40.0", + "binary-tree-typed": "^1.41.0", + "bst-typed": "^1.41.0", "dependency-cruiser": "^14.1.0", "eslint": "^8.50.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.28.1", - "heap-typed": "^1.40.0", + "heap-typed": "^1.41.0", "istanbul-badges-readme": "^1.8.5", "jest": "^29.7.0", "prettier": "^3.0.3", diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts index d98a67c..df4790a 100644 --- a/src/data-structures/binary-tree/avl-tree.ts +++ b/src/data-structures/binary-tree/avl-tree.ts @@ -21,7 +21,8 @@ export class AVLTreeNode = AVLTreeNodeNeste export class AVLTree = AVLTreeNode>> extends BST - implements IBinaryTree { + implements IBinaryTree +{ /** * This is a constructor function for an AVL tree data structure in TypeScript. * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the @@ -160,7 +161,7 @@ export class AVLTree = AVLTreeNode = BinaryTree * @template N - The type of the binary tree's nodes. */ export class BinaryTree = BinaryTreeNode>> - implements IBinaryTree { + implements IBinaryTree +{ iterationType: IterationType = IterationType.ITERATIVE; /** @@ -201,7 +202,7 @@ export class BinaryTree = BinaryTreeNode } const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined; - const existNode = key !== undefined ? this.get(key, (node: N) => node.key) : undefined; + const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined; if (this.root) { if (existNode) { @@ -290,7 +291,7 @@ export class BinaryTree = BinaryTreeNode if (!this.root) return bstDeletedResult; if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; - const curr = this.get(identifier, callback); + const curr = this.getNode(identifier, callback); if (!curr) return bstDeletedResult; const parent: N | null = curr?.parent ? curr.parent : null; @@ -342,8 +343,8 @@ export class BinaryTree = BinaryTreeNode * @returns the depth of the `distNode` relative to the `beginRoot`. */ getDepth(distNode: BTNKey | N | null, beginRoot: BTNKey | N | null = this.root): number { - if (typeof distNode === 'number') distNode = this.get(distNode); - if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot); + if (typeof distNode === 'number') distNode = this.getNode(distNode); + if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot); let depth = 0; while (distNode?.parent) { if (distNode === beginRoot) { @@ -368,7 +369,7 @@ export class BinaryTree = BinaryTreeNode * @returns the height of the binary tree. */ getHeight(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): number { - if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot); + if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot); if (!beginRoot) return -1; if (iterationType === IterationType.RECURSIVE) { @@ -385,7 +386,7 @@ export class BinaryTree = BinaryTreeNode return -1; } - const stack: { node: N; depth: number }[] = [{node: beginRoot, depth: 0}]; + const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}]; let maxHeight = 0; while (stack.length > 0) { @@ -604,21 +605,21 @@ export class BinaryTree = BinaryTreeNode return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0; } - get>( + getNode>( identifier: BTNKey, callback?: C, beginRoot?: N, iterationType?: IterationType ): N | null; - get>( + getNode>( identifier: N | null, callback?: C, beginRoot?: N, iterationType?: IterationType ): N | null; - get>( + getNode>( identifier: ReturnType, callback: C, beginRoot?: N, @@ -640,7 +641,7 @@ export class BinaryTree = BinaryTreeNode * performed when searching for a node in the binary tree. It can have one of the following values: * @returns either the found node (of type N) or null if no node is found. */ - get>( + getNode>( identifier: ReturnType | null, callback: C = ((node: N) => node.key) as C, beginRoot = this.root, @@ -651,6 +652,53 @@ export class BinaryTree = BinaryTreeNode return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null; } + get>( + identifier: BTNKey, + callback?: C, + beginRoot?: N, + iterationType?: IterationType + ): V | undefined; + + get>( + identifier: N | null, + callback?: C, + beginRoot?: N, + iterationType?: IterationType + ): V | undefined; + + get>( + identifier: ReturnType, + callback: C, + beginRoot?: N, + iterationType?: IterationType + ): V | undefined; + + /** + * The function `get` returns the first node value in a binary tree that matches the given property or key. + * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of + * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N` + * type. + * @param callback - The `callback` parameter is a function that is used to determine whether a node + * matches the desired criteria. It takes a node as input and returns a boolean value indicating + * whether the node matches the criteria or not. The default callback function + * (`((node: N) => node.key)`) is used if no callback function is + * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies + * the root node from which the search should begin. + * @param iterationType - The `iterationType` parameter specifies the type of iteration to be + * performed when searching for a node in the binary tree. It can have one of the following values: + * @returns either the found value (of type V) or undefined if no node value is found. + */ + get>( + identifier: ReturnType | null, + callback: C = ((node: N) => node.key) as C, + beginRoot = this.root, + iterationType = this.iterationType + ): V | undefined { + if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; + // TODO may support finding node by value equal + return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0].value ?? undefined; + } + /** * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing * up to the root node, with the option to reverse the order of the nodes. @@ -686,7 +734,7 @@ export class BinaryTree = BinaryTreeNode * no leftmost node, it returns `null`. */ getLeftMost(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): N | null { - if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot); + if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot); if (!beginRoot) return beginRoot; @@ -812,7 +860,7 @@ export class BinaryTree = BinaryTreeNode beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType ): ReturnType[] { - if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot); + if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot); const ans: ReturnType>[] = []; if (!beginRoot) return ans; @@ -888,7 +936,7 @@ export class BinaryTree = BinaryTreeNode _traverse(beginRoot); } else { // 0: visit, 1: print - const stack: { opt: 0 | 1; node: N | null | undefined }[] = [{opt: 0, node: beginRoot}]; + const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}]; while (stack.length > 0) { const cur = stack.pop(); @@ -960,7 +1008,7 @@ export class BinaryTree = BinaryTreeNode if (current.right) queue.push(current.right); traverse(level + 1); - } + }; traverse(0); } else { @@ -1055,7 +1103,7 @@ export class BinaryTree = BinaryTreeNode * @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null` * if there is no successor, or `undefined` if the input `x` is `undefined`. */ - getSuccessor(x: N): N | null | undefined{ + getSuccessor(x: N): N | null | undefined { if (x.right) { return this.getLeftMost(x.right); } @@ -1178,7 +1226,7 @@ export class BinaryTree = BinaryTreeNode * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the * binary tree nodes in a specific order. */ - * [Symbol.iterator](node = this.root): Generator { + *[Symbol.iterator](node = this.root): Generator { if (!node) { return; } diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 2d8a8b1..7fad37f 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -19,7 +19,8 @@ export class BSTNode = BSTNodeNested> extend export class BST = BSTNode>> extends BinaryTree - implements IBinaryTree { + implements IBinaryTree +{ /** * The constructor function initializes a binary search tree object with an optional comparator * function. @@ -153,7 +154,9 @@ export class BST = BSTNode> return super.addMany(keysOrNodes, data); } const inserted: (N | null | undefined)[] = []; - const combinedArr: [BTNKey | N, V][] = keysOrNodes.map((value:(BTNKey | N), index) => [value, data?.[index]] as [BTNKey | N, V]); + const combinedArr: [BTNKey | N, V][] = keysOrNodes.map( + (value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V] + ); let sorted = []; function isNodeOrNullTuple(arr: [BTNKey | N, V][]): arr is [N, V][] { @@ -231,7 +234,7 @@ export class BST = BSTNode> * @returns either the first node that matches the given nodeProperty and callback, or null if no * matching node is found. */ - override get>( + override getNode>( identifier: ReturnType | null, callback: C = ((node: N) => node.key) as C, beginRoot = this.root, @@ -362,7 +365,7 @@ export class BST = BSTNode> targetNode: BTNKey | N | null = this.root, iterationType = this.iterationType ): ReturnType[] { - if (typeof targetNode === 'number') targetNode = this.get(targetNode); + if (typeof targetNode === 'number') targetNode = this.getNode(targetNode); const ans: ReturnType>[] = []; if (!targetNode) return ans; const targetKey = targetNode.key; diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 41a9fb4..f256e40 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -1,27 +1,26 @@ -import {RBTNColor} from "../../types"; +import {RBTNColor} from '../../types'; export class RBTreeNode { - key: number = 0; + key: number; parent: RBTreeNode; left: RBTreeNode; right: RBTreeNode; color: number = RBTNColor.BLACK; - constructor() { + constructor(key: number, color: RBTNColor = RBTNColor.BLACK) { + this.key = key; + this.color = color; this.parent = null as unknown as RBTreeNode; this.left = null as unknown as RBTreeNode; this.right = null as unknown as RBTreeNode; } } +export const SN = new RBTreeNode(0); + export class RedBlackTree { - constructor() { - this._NIL = new RBTreeNode(); - this.NIL.color = RBTNColor.BLACK; - this.NIL.left = null as unknown as RBTreeNode; - this.NIL.right = null as unknown as RBTreeNode; - this._root = this.NIL; + this._root = SN; } protected _root: RBTreeNode; @@ -30,12 +29,6 @@ export class RedBlackTree { return this._root; } - protected _NIL: RBTreeNode; - - get NIL(): RBTreeNode { - return this._NIL; - } - /** * The `insert` function inserts a new node with a given key into a red-black tree and fixes any * violations of the red-black tree properties. @@ -44,18 +37,14 @@ export class RedBlackTree { * @returns The function does not explicitly return anything. */ insert(key: number): void { - - const node: RBTreeNode = new RBTreeNode(); - node.parent = null as unknown as RBTreeNode; - node.key = key; - node.left = this.NIL; - node.right = this.NIL; - node.color = RBTNColor.RED; + const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED); + node.left = SN; + node.right = SN; let y: RBTreeNode = null as unknown as RBTreeNode; let x: RBTreeNode = this.root; - while (x !== this.NIL) { + while (x !== SN) { y = x; if (node.key < x.key) { x = x.left; @@ -94,10 +83,9 @@ export class RedBlackTree { */ delete(key: number): void { const helper = (node: RBTreeNode): void => { - - let z: RBTreeNode = this.NIL; + let z: RBTreeNode = SN; let x: RBTreeNode, y: RBTreeNode; - while (node !== this.NIL) { + while (node !== SN) { if (node.key === key) { z = node; } @@ -109,16 +97,16 @@ export class RedBlackTree { } } - if (z === this.NIL) { + if (z === SN) { return; } y = z; let yOriginalColor: number = y.color; - if (z.left === this.NIL) { + if (z.left === SN) { x = z.right; this._rbTransplant(z, z.right); - } else if (z.right === this.NIL) { + } else if (z.right === SN) { x = z.left; this._rbTransplant(z, z.left); } else { @@ -138,13 +126,17 @@ export class RedBlackTree { y.left.parent = y; y.color = z.color; } - if (yOriginalColor === 0) { + if (yOriginalColor === RBTNColor.BLACK) { this._fixDelete(x); } - } + }; helper(this.root); } + isRealNode(node: RBTreeNode): node is RBTreeNode { + return node !== SN && node !== null; + } + /** * The function `getNode` is a recursive depth-first search algorithm that searches for a node with a * given key in a red-black tree. @@ -157,40 +149,40 @@ export class RedBlackTree { */ getNode(key: number, beginRoot = this.root): RBTreeNode { const dfs = (node: RBTreeNode): RBTreeNode => { - if (node === this.NIL || key === node.key) { - return node; - } + if (this.isRealNode(node)) { + if (key === node.key) { + return node; + } - if (key < node.key) { - return dfs(node.left); + if (key < node.key) return dfs(node.left); + return dfs(node.right); + } else { + return null as unknown as RBTreeNode; } - return dfs(node.right); - } + }; return dfs(beginRoot); } - /** * The function returns the leftmost node in a red-black tree. * @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode, which represents a node in * a Red-Black Tree. * @returns The leftmost node in the given RBTreeNode. */ - getLeftMost(node: RBTreeNode): RBTreeNode { - while (node.left !== null && node.left !== this.NIL) { + getLeftMost(node: RBTreeNode = this.root): RBTreeNode { + while (node.left !== null && node.left !== SN) { node = node.left; } return node; } - /** * The function returns the rightmost node in a red-black tree. * @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode. * @returns the rightmost node in a red-black tree. */ getRightMost(node: RBTreeNode): RBTreeNode { - while (node.right !== null && node.right !== this.NIL) { + while (node.right !== null && node.right !== SN) { node = node.right; } return node; @@ -202,13 +194,12 @@ export class RedBlackTree { * @returns the successor of the given RBTreeNode. */ getSuccessor(x: RBTreeNode): RBTreeNode { - - if (x.right !== this.NIL) { + if (x.right !== SN) { return this.getLeftMost(x.right); } let y: RBTreeNode = x.parent; - while (y !== this.NIL && y !== null && x === y.right) { + while (y !== SN && y !== null && x === y.right) { x = y; y = y.parent; } @@ -222,13 +213,12 @@ export class RedBlackTree { * @returns the predecessor of the given RBTreeNode 'x'. */ getPredecessor(x: RBTreeNode): RBTreeNode { - - if (x.left !== this.NIL) { + if (x.left !== SN) { return this.getRightMost(x.left); } let y: RBTreeNode = x.parent; - while (y !== this.NIL && x === y.left) { + while (y !== SN && x === y.left) { x = y; y = y.parent; } @@ -243,7 +233,7 @@ export class RedBlackTree { protected _leftRotate(x: RBTreeNode): void { const y: RBTreeNode = x.right; x.right = y.left; - if (y.left !== this.NIL) { + if (y.left !== SN) { y.left.parent = x; } y.parent = x.parent; @@ -266,7 +256,7 @@ export class RedBlackTree { protected _rightRotate(x: RBTreeNode): void { const y: RBTreeNode = x.left; x.left = y.right; - if (y.right !== this.NIL) { + if (y.right !== SN) { y.right.parent = x; } y.parent = x.parent; @@ -288,24 +278,21 @@ export class RedBlackTree { */ protected _fixDelete(x: RBTreeNode): void { let s: RBTreeNode; - while (x !== this.root && x.color === 0) { + while (x !== this.root && x.color === RBTNColor.BLACK) { if (x === x.parent.left) { s = x.parent.right; if (s.color === 1) { - s.color = RBTNColor.BLACK; x.parent.color = RBTNColor.RED; this._leftRotate(x.parent); s = x.parent.right; } - if (s.left.color === 0 && s.right.color === 0) { - + if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) { s.color = RBTNColor.RED; x = x.parent; } else { - if (s.right.color === 0) { - + if (s.right.color === RBTNColor.BLACK) { s.left.color = RBTNColor.BLACK; s.color = RBTNColor.RED; this._rightRotate(s); @@ -321,20 +308,17 @@ export class RedBlackTree { } else { s = x.parent.left; if (s.color === 1) { - s.color = RBTNColor.BLACK; x.parent.color = RBTNColor.RED; this._rightRotate(x.parent); s = x.parent.left; } - if (s.right.color === 0 && s.right.color === 0) { - + if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) { s.color = RBTNColor.RED; x = x.parent; } else { - if (s.left.color === 0) { - + if (s.left.color === RBTNColor.BLACK) { s.right.color = RBTNColor.BLACK; s.color = RBTNColor.RED; this._leftRotate(s); @@ -379,14 +363,12 @@ export class RedBlackTree { if (k.parent === k.parent.parent.right) { u = k.parent.parent.left; if (u.color === 1) { - u.color = RBTNColor.BLACK; k.parent.color = RBTNColor.BLACK; k.parent.parent.color = RBTNColor.RED; k = k.parent.parent; } else { if (k === k.parent.left) { - k = k.parent; this._rightRotate(k); } @@ -399,14 +381,12 @@ export class RedBlackTree { u = k.parent.parent.right; if (u.color === 1) { - u.color = RBTNColor.BLACK; k.parent.color = RBTNColor.BLACK; k.parent.parent.color = RBTNColor.RED; k = k.parent.parent; } else { if (k === k.parent.right) { - k = k.parent; this._leftRotate(k); } @@ -422,4 +402,4 @@ export class RedBlackTree { } this.root.color = RBTNColor.BLACK; } -} \ No newline at end of file +} diff --git a/src/data-structures/binary-tree/tree-multiset.ts b/src/data-structures/binary-tree/tree-multiset.ts index 7bea74a..84e2b64 100644 --- a/src/data-structures/binary-tree/tree-multiset.ts +++ b/src/data-structures/binary-tree/tree-multiset.ts @@ -37,7 +37,8 @@ export class TreeMultisetNode< */ export class TreeMultiset = TreeMultisetNode>> extends AVLTree - implements IBinaryTree { + implements IBinaryTree +{ /** * The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to * merge duplicated values. @@ -169,7 +170,7 @@ export class TreeMultiset = TreeMultis } else if (parent.right === undefined) { parent.right = newNode; if (newNode !== null) { - this._size = (this.size + 1); + this._size = this.size + 1; this._setCount(this.count + newNode.count); } return parent.right; @@ -282,7 +283,7 @@ export class TreeMultiset = TreeMultis const bstDeletedResult: BinaryTreeDeletedResult[] = []; if (!this.root) return bstDeletedResult; - const curr: N | null = this.get(identifier, callback); + const curr: N | null = this.getNode(identifier, callback); if (!curr) return bstDeletedResult; const parent: N | null = curr?.parent ? curr.parent : null; diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts index 6cd5504..09bc5b5 100644 --- a/src/data-structures/graph/abstract-graph.ts +++ b/src/data-structures/graph/abstract-graph.ts @@ -26,7 +26,6 @@ export abstract class AbstractVertex { this.key = key; this.value = value; } - } export abstract class AbstractEdge { @@ -65,7 +64,8 @@ export abstract class AbstractGraph< E = any, VO extends AbstractVertex = AbstractVertex, EO extends AbstractEdge = AbstractEdge -> implements IGraph { +> implements IGraph +{ protected _vertices: Map = new Map(); get vertices(): Map { @@ -513,14 +513,14 @@ export abstract class AbstractGraph< } getMinDist && - distMap.forEach((d, v) => { - if (v !== srcVertex) { - if (d < minDist) { - minDist = d; - if (genPaths) minDest = v; + distMap.forEach((d, v) => { + if (v !== srcVertex) { + if (d < minDist) { + minDist = d; + if (genPaths) minDest = v; + } } - } - }); + }); genPaths && getPaths(minDest); @@ -582,7 +582,7 @@ export abstract class AbstractGraph< if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity); } - const heap = new PriorityQueue<{ key: number; value: VO }>({comparator: (a, b) => a.key - b.key}); + const heap = new PriorityQueue<{key: number; value: VO}>({comparator: (a, b) => a.key - b.key}); heap.add({key: 0, value: srcVertex}); distMap.set(srcVertex, 0); @@ -811,7 +811,7 @@ export abstract class AbstractGraph< * `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest * path between vertices in the */ - floyd(): { costs: number[][]; predecessor: (VO | null)[][] } { + floyd(): {costs: number[][]; predecessor: (VO | null)[][]} { const idAndVertices = [...this._vertices]; const n = idAndVertices.length; @@ -996,5 +996,4 @@ export abstract class AbstractGraph< protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey { return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey; } - } diff --git a/src/data-structures/graph/directed-graph.ts b/src/data-structures/graph/directed-graph.ts index 23fd02d..67b16cb 100644 --- a/src/data-structures/graph/directed-graph.ts +++ b/src/data-structures/graph/directed-graph.ts @@ -46,13 +46,14 @@ export class DirectedEdge extends AbstractEdge { } export class DirectedGraph< - V = any, - E = any, - VO extends DirectedVertex = DirectedVertex, - EO extends DirectedEdge = DirectedEdge -> + V = any, + E = any, + VO extends DirectedVertex = DirectedVertex, + EO extends DirectedEdge = DirectedEdge + > extends AbstractGraph - implements IGraph { + implements IGraph +{ /** * The constructor function initializes an instance of a class. */ diff --git a/src/data-structures/graph/undirected-graph.ts b/src/data-structures/graph/undirected-graph.ts index 75f15fc..2e534c9 100644 --- a/src/data-structures/graph/undirected-graph.ts +++ b/src/data-structures/graph/undirected-graph.ts @@ -43,13 +43,14 @@ export class UndirectedEdge extends AbstractEdge { } export class UndirectedGraph< - V = any, - E = any, - VO extends UndirectedVertex = UndirectedVertex, - EO extends UndirectedEdge = UndirectedEdge -> + V = any, + E = any, + VO extends UndirectedVertex = UndirectedVertex, + EO extends UndirectedEdge = UndirectedEdge + > extends AbstractGraph - implements IGraph { + implements IGraph +{ /** * The constructor initializes a new Map object to store edges. */ diff --git a/src/data-structures/hash/hash-map.ts b/src/data-structures/hash/hash-map.ts index cb59fc3..9595be5 100644 --- a/src/data-structures/hash/hash-map.ts +++ b/src/data-structures/hash/hash-map.ts @@ -133,7 +133,7 @@ export class HashMap { } } - * entries(): IterableIterator<[K, V]> { + *entries(): IterableIterator<[K, V]> { for (const bucket of this.table) { if (bucket) { for (const [key, value] of bucket) { diff --git a/src/data-structures/hash/tree-map.ts b/src/data-structures/hash/tree-map.ts index a6d743d..fe86360 100644 --- a/src/data-structures/hash/tree-map.ts +++ b/src/data-structures/hash/tree-map.ts @@ -1,2 +1 @@ -export class TreeMap { -} +export class TreeMap {} diff --git a/src/data-structures/hash/tree-set.ts b/src/data-structures/hash/tree-set.ts index 65f14db..591aeda 100644 --- a/src/data-structures/hash/tree-set.ts +++ b/src/data-structures/hash/tree-set.ts @@ -1,2 +1 @@ -export class TreeSet { -} +export class TreeSet {} diff --git a/src/data-structures/heap/heap.ts b/src/data-structures/heap/heap.ts index 999454a..60d4533 100644 --- a/src/data-structures/heap/heap.ts +++ b/src/data-structures/heap/heap.ts @@ -8,7 +8,7 @@ import type {Comparator, DFSOrderPattern} from '../../types'; export class Heap { - constructor(options: { comparator: Comparator; nodes?: E[] }) { + constructor(options: {comparator: Comparator; nodes?: E[]}) { this._comparator = options.comparator; if (options.nodes && options.nodes.length > 0) { this._nodes = options.nodes; @@ -48,7 +48,7 @@ export class Heap { * @returns A new Heap instance. * @param options */ - static heapify(options: { nodes: E[]; comparator: Comparator }): Heap { + static heapify(options: {nodes: E[]; comparator: Comparator}): Heap { return new Heap(options); } diff --git a/src/data-structures/heap/max-heap.ts b/src/data-structures/heap/max-heap.ts index 139ef64..be2c9b1 100644 --- a/src/data-structures/heap/max-heap.ts +++ b/src/data-structures/heap/max-heap.ts @@ -11,7 +11,7 @@ import type {Comparator} from '../../types'; export class MaxHeap extends Heap { constructor( - options: { comparator: Comparator; nodes?: E[] } = { + options: {comparator: Comparator; nodes?: E[]} = { comparator: (a: E, b: E) => { if (!(typeof a === 'number' && typeof b === 'number')) { throw new Error('The a, b params of compare function must be number'); diff --git a/src/data-structures/heap/min-heap.ts b/src/data-structures/heap/min-heap.ts index 5057017..dc86f87 100644 --- a/src/data-structures/heap/min-heap.ts +++ b/src/data-structures/heap/min-heap.ts @@ -11,7 +11,7 @@ import type {Comparator} from '../../types'; export class MinHeap extends Heap { constructor( - options: { comparator: Comparator; nodes?: E[] } = { + options: {comparator: Comparator; nodes?: E[]} = { comparator: (a: E, b: E) => { if (!(typeof a === 'number' && typeof b === 'number')) { throw new Error('The a, b params of compare function must be number'); diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index 41b9dc9..119ae71 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -594,7 +594,7 @@ export class DoublyLinkedList { /** * The function returns an iterator that iterates over the values of a linked list. */ - * [Symbol.iterator]() { + *[Symbol.iterator]() { let current = this.head; while (current) { diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index 04c0bbe..7c39cf6 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -565,7 +565,7 @@ export class SinglyLinkedList { /** * The function returns an iterator that iterates over the values of a linked list. */ - * [Symbol.iterator]() { + *[Symbol.iterator]() { let current = this.head; while (current) { diff --git a/src/data-structures/matrix/matrix.ts b/src/data-structures/matrix/matrix.ts index 4f1b8b8..3559d58 100644 --- a/src/data-structures/matrix/matrix.ts +++ b/src/data-structures/matrix/matrix.ts @@ -14,7 +14,7 @@ export class MatrixNTI2D { * given initial value or 0 if not provided. * @param options - An object containing the following properties: */ - constructor(options: { row: number; col: number; initialVal?: V }) { + constructor(options: {row: number; col: number; initialVal?: V}) { const {row, col, initialVal} = options; this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0)); } diff --git a/src/data-structures/matrix/vector2d.ts b/src/data-structures/matrix/vector2d.ts index 2f62f4e..1b2ff44 100644 --- a/src/data-structures/matrix/vector2d.ts +++ b/src/data-structures/matrix/vector2d.ts @@ -10,8 +10,7 @@ export class Vector2D { public x: number = 0, public y: number = 0, public w: number = 1 // needed for matrix multiplication - ) { - } + ) {} /** * The function checks if the x and y values of a point are both zero. diff --git a/src/data-structures/priority-queue/max-priority-queue.ts b/src/data-structures/priority-queue/max-priority-queue.ts index 409c99f..dbb0793 100644 --- a/src/data-structures/priority-queue/max-priority-queue.ts +++ b/src/data-structures/priority-queue/max-priority-queue.ts @@ -10,7 +10,7 @@ import type {Comparator} from '../../types'; export class MaxPriorityQueue extends PriorityQueue { constructor( - options: { comparator: Comparator; nodes?: E[] } = { + options: {comparator: Comparator; nodes?: E[]} = { comparator: (a: E, b: E) => { if (!(typeof a === 'number' && typeof b === 'number')) { throw new Error('The a, b params of compare function must be number'); diff --git a/src/data-structures/priority-queue/min-priority-queue.ts b/src/data-structures/priority-queue/min-priority-queue.ts index da8ab64..8b8386f 100644 --- a/src/data-structures/priority-queue/min-priority-queue.ts +++ b/src/data-structures/priority-queue/min-priority-queue.ts @@ -10,7 +10,7 @@ import type {Comparator} from '../../types'; export class MinPriorityQueue extends PriorityQueue { constructor( - options: { comparator: Comparator; nodes?: E[] } = { + options: {comparator: Comparator; nodes?: E[]} = { comparator: (a: E, b: E) => { if (!(typeof a === 'number' && typeof b === 'number')) { throw new Error('The a, b params of compare function must be number'); diff --git a/src/data-structures/priority-queue/priority-queue.ts b/src/data-structures/priority-queue/priority-queue.ts index 60deb98..edfbaf2 100644 --- a/src/data-structures/priority-queue/priority-queue.ts +++ b/src/data-structures/priority-queue/priority-queue.ts @@ -10,7 +10,7 @@ import {Heap} from '../heap'; import {Comparator} from '../../types'; export class PriorityQueue extends Heap { - constructor(options: { comparator: Comparator; nodes?: E[] }) { + constructor(options: {comparator: Comparator; nodes?: E[]}) { super(options); } } diff --git a/src/data-structures/queue/deque.ts b/src/data-structures/queue/deque.ts index f0911ab..413af8f 100644 --- a/src/data-structures/queue/deque.ts +++ b/src/data-structures/queue/deque.ts @@ -9,8 +9,7 @@ import {DoublyLinkedList} from '../linked-list'; // O(n) time complexity of obtaining the value // O(1) time complexity of adding at the beginning and the end -export class Deque extends DoublyLinkedList { -} +export class Deque extends DoublyLinkedList {} // O(1) time complexity of obtaining the value // O(n) time complexity of adding at the beginning and the end @@ -20,9 +19,9 @@ export class ObjectDeque { if (capacity !== undefined) this._capacity = capacity; } - protected _nodes: { [key: number]: E } = {}; + protected _nodes: {[key: number]: E} = {}; - get nodes(): { [p: number]: E } { + get nodes(): {[p: number]: E} { return this._nodes; } diff --git a/src/data-structures/queue/queue.ts b/src/data-structures/queue/queue.ts index 6222f35..9991f38 100644 --- a/src/data-structures/queue/queue.ts +++ b/src/data-structures/queue/queue.ts @@ -201,7 +201,7 @@ export class Queue { return new Queue(this.nodes.slice(this.offset)); } - * [Symbol.iterator]() { + *[Symbol.iterator]() { for (const item of this.nodes) { yield item; } diff --git a/src/types/data-structures/matrix/navigator.ts b/src/types/data-structures/matrix/navigator.ts index 34eddd9..9d8b9a9 100644 --- a/src/types/data-structures/matrix/navigator.ts +++ b/src/types/data-structures/matrix/navigator.ts @@ -1,6 +1,6 @@ export type Direction = 'up' | 'right' | 'down' | 'left'; -export type Turning = { [key in Direction]: Direction }; +export type Turning = {[key in Direction]: Direction}; export type NavigatorParams = { matrix: T[][]; diff --git a/src/types/utils/utils.ts b/src/types/utils/utils.ts index 1f3a505..f4d26c4 100644 --- a/src/types/utils/utils.ts +++ b/src/types/utils/utils.ts @@ -1,5 +1,5 @@ export type ToThunkFn = () => ReturnType; -export type Thunk = () => ReturnType & { __THUNK__: symbol }; +export type Thunk = () => ReturnType & {__THUNK__: symbol}; export type TrlFn = (...args: any[]) => any; export type TrlAsyncFn = (...args: any[]) => any; diff --git a/src/types/utils/validate-type.ts b/src/types/utils/validate-type.ts index 3ebf451..ac9ff28 100644 --- a/src/types/utils/validate-type.ts +++ b/src/types/utils/validate-type.ts @@ -1,6 +1,6 @@ -export type KeyValueObject = { [key: string]: any }; +export type KeyValueObject = {[key: string]: any}; -export type KeyValueObjectWithKey = { [key: string]: any; key: string | number | symbol }; +export type KeyValueObjectWithKey = {[key: string]: any; key: string | number | symbol}; export type NonNumberNonObjectButDefined = string | boolean | symbol | null; diff --git a/test/unit/data-structures/binary-tree/avl-tree.test.ts b/test/unit/data-structures/binary-tree/avl-tree.test.ts index eb0cf8a..7518a9b 100644 --- a/test/unit/data-structures/binary-tree/avl-tree.test.ts +++ b/test/unit/data-structures/binary-tree/avl-tree.test.ts @@ -7,18 +7,18 @@ describe('AVL Tree Test', () => { for (const i of arr) tree.add(i, i); - const node6 = tree.get(6); + const node6 = tree.getNode(6); expect(node6 && tree.getHeight(node6)).toBe(3); expect(node6 && tree.getDepth(node6)).toBe(1); - const getNodeById = tree.get(10); + const getNodeById = tree.getNode(10); expect(getNodeById?.key).toBe(10); const getMinNodeByRoot = tree.getLeftMost(); expect(getMinNodeByRoot?.key).toBe(1); - const node15 = tree.get(15); + const node15 = tree.getNode(15); const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15); expect(getMinNodeBySpecificNode?.key).toBe(12); @@ -116,18 +116,18 @@ describe('AVL Tree Test recursively', () => { for (const i of arr) tree.add(i, i); - const node6 = tree.get(6); + const node6 = tree.getNode(6); expect(node6 && tree.getHeight(node6)).toBe(3); expect(node6 && tree.getDepth(node6)).toBe(1); - const getNodeById = tree.get(10); + const getNodeById = tree.getNode(10); expect(getNodeById?.key).toBe(10); const getMinNodeByRoot = tree.getLeftMost(); expect(getMinNodeByRoot?.key).toBe(1); - const node15 = tree.get(15); + const node15 = tree.getNode(15); const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15); expect(getMinNodeBySpecificNode?.key).toBe(12); diff --git a/test/unit/data-structures/binary-tree/binary-tree.test.ts b/test/unit/data-structures/binary-tree/binary-tree.test.ts index e141fec..5970b72 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -107,7 +107,7 @@ describe('BinaryTree', () => { expect(tree.has(2)).toBe(true); expect(tree.has(3)).toBe(true); expect(tree.has(4)).toBe(false); - const node4 = tree.get(4); + const node4 = tree.getNode(4); expect(tree.has(node4)).toBe(false); expect(tree.has(node4, node => node)).toBe(false); expect(tree.has('3', node => node.value?.toString())).toBe(true); @@ -169,13 +169,13 @@ describe('BinaryTree', () => { new BinaryTreeNode(4, 4) ]); - expect(tree.isSubtreeBST(tree.get(4), IterationType.RECURSIVE)).toBe(true); - expect(tree.isSubtreeBST(tree.get(4), IterationType.ITERATIVE)).toBe(true); + expect(tree.isSubtreeBST(tree.getNode(4), IterationType.RECURSIVE)).toBe(true); + expect(tree.isSubtreeBST(tree.getNode(4), IterationType.ITERATIVE)).toBe(true); }); it('should subTreeTraverse', () => { tree.addMany([4, 2, 6, 1, 3, 5, 7]); - expect(tree.subTreeTraverse(node => node.key, tree.get(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]); + expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]); }); it('should clear the tree', () => { @@ -234,9 +234,9 @@ describe('BinaryTree Morris Traversal', () => { }); it('after morris traversals should the structure of the tree be correct', () => { - const node1 = tree.get(1); - const node2 = tree.get(2); - const node3 = tree.get(3); + const node1 = tree.getNode(1); + const node2 = tree.getNode(2); + const node3 = tree.getNode(3); expect(node1?.left).toBe(node2); expect(node1?.right).toBe(node3); }); @@ -339,8 +339,8 @@ describe('BinaryTree', () => { tree.add(3, 'B'); tree.add(7, 'C'); - const nodeA = tree.get(5); - const nodeB = tree.get(3); + const nodeA = tree.getNode(5); + const nodeB = tree.getNode(3); expect(nodeA?.key).toBe(5); expect(nodeA?.value).toBe('A'); @@ -351,7 +351,7 @@ describe('BinaryTree', () => { it('should return null when getting a non-existent node', () => { tree.add(5, 'A'); - const node = tree.get(3); + const node = tree.getNode(3); expect(node).toBe(null); }); @@ -421,7 +421,7 @@ describe('BinaryTree', () => { tree.delete(3); expect(tree.size).toBe(2); - expect(tree.get(3)).toBe(null); + expect(tree.getNode(3)).toBe(null); }); it('should check if the tree is perfectly balanced', () => { diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index 7d6a5ab..0d9b295 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -19,20 +19,20 @@ describe('BST operations test', () => { expect(bst.has(6)).toBe(true); - const node6 = bst.get(6); + const node6 = bst.getNode(6); expect(node6 && bst.getHeight(6)).toBe(2); expect(node6 && bst.getDepth(6)).toBe(3); - const nodeId10 = bst.get(10); + const nodeId10 = bst.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = bst.get(9, node => node.value); + const nodeVal9 = bst.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); const leftMost = bst.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = bst.get(15); + const node15 = bst.getNode(15); const minNodeBySpecificNode = node15 && bst.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -46,7 +46,7 @@ describe('BST operations test', () => { expect(node15).toBeInstanceOf(BSTNode); - const node11 = bst.get(11); + const node11 = bst.getNode(11); expect(node11).toBeInstanceOf(BSTNode); const dfsInorderNodes = bst.dfs(node => node, 'in'); @@ -222,20 +222,20 @@ describe('BST operations test', () => { expect(objBST.has(6)).toBe(true); - const node6 = objBST.get(6); + const node6 = objBST.getNode(6); expect(node6 && objBST.getHeight(node6)).toBe(2); expect(node6 && objBST.getDepth(node6)).toBe(3); - const nodeId10 = objBST.get(10); + const nodeId10 = objBST.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = objBST.get(9); + const nodeVal9 = objBST.getNode(9); expect(nodeVal9?.key).toBe(9); const leftMost = objBST.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = objBST.get(15); + const node15 = objBST.getNode(15); expect(node15?.value).toEqual({key: 15, keyA: 15}); const minNodeBySpecificNode = node15 && objBST.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -250,7 +250,7 @@ describe('BST operations test', () => { expect(node15).toBeInstanceOf(BSTNode); - const node11 = objBST.get(11); + const node11 = objBST.getNode(11); expect(node11).toBeInstanceOf(BSTNode); const dfsInorderNodes = objBST.dfs(node => node, 'in'); @@ -409,20 +409,21 @@ describe('BST operations test recursively', () => { expect(bst.has(6)).toBe(true); - const node6 = bst.get(6); + const node6 = bst.getNode(6); expect(node6 && bst.getHeight(6)).toBe(2); expect(node6 && bst.getDepth(6)).toBe(3); - const nodeId10 = bst.get(10); + const nodeId10 = bst.getNode(10); + expect(bst.get(10)).toBe(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = bst.get(9, node => node.value); + const nodeVal9 = bst.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); const leftMost = bst.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = bst.get(15); + const node15 = bst.getNode(15); const minNodeBySpecificNode = node15 && bst.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -436,7 +437,7 @@ describe('BST operations test recursively', () => { expect(node15).toBeInstanceOf(BSTNode); - const node11 = bst.get(11); + const node11 = bst.getNode(11); expect(node11).toBeInstanceOf(BSTNode); const dfsInorderNodes = bst.dfs(node => node, 'in'); @@ -612,20 +613,21 @@ describe('BST operations test recursively', () => { expect(objBST.has(6)).toBe(true); - const node6 = objBST.get(6); + const node6 = objBST.getNode(6); + expect(objBST.get(6)).toEqual({key: 6, keyA: 6}); expect(node6 && objBST.getHeight(node6)).toBe(2); expect(node6 && objBST.getDepth(node6)).toBe(3); - const nodeId10 = objBST.get(10); + const nodeId10 = objBST.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = objBST.get(9); + const nodeVal9 = objBST.getNode(9); expect(nodeVal9?.key).toBe(9); const leftMost = objBST.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = objBST.get(15); + const node15 = objBST.getNode(15); expect(node15?.value).toEqual({key: 15, keyA: 15}); const minNodeBySpecificNode = node15 && objBST.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -640,7 +642,7 @@ describe('BST operations test recursively', () => { expect(node15).toBeInstanceOf(BSTNode); - const node11 = objBST.get(11); + const node11 = objBST.getNode(11); expect(node11).toBeInstanceOf(BSTNode); const dfsInorderNodes = objBST.dfs(node => node, 'in'); diff --git a/test/unit/data-structures/binary-tree/overall.test.ts b/test/unit/data-structures/binary-tree/overall.test.ts index 520c2bc..d168b1c 100644 --- a/test/unit/data-structures/binary-tree/overall.test.ts +++ b/test/unit/data-structures/binary-tree/overall.test.ts @@ -20,8 +20,8 @@ describe('Overall BinaryTree Test', () => { leftMost?.key === 1; // true expect(leftMost?.key).toBe(1); bst.delete(6); - bst.get(6); // null - expect(bst.get(6)).toBeNull(); + bst.getNode(6); // null + expect(bst.getNode(6)).toBeNull(); bst.isAVLBalanced(); // true or false expect(bst.isAVLBalanced()).toBe(true); const bfsIDs: number[] = []; diff --git a/test/unit/data-structures/binary-tree/rb-tree.test.ts b/test/unit/data-structures/binary-tree/rb-tree.test.ts index 37b8643..a929689 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -1,5 +1,5 @@ -import { RedBlackTree, RBTreeNode } from '../../../../src'; -import {getRandomInt} from "../../../utils"; +import {RBTreeNode, RedBlackTree, SN} from '../../../../src'; +import {getRandomInt} from '../../../utils'; describe('RedBlackTree', () => { let tree: RedBlackTree; @@ -17,7 +17,7 @@ describe('RedBlackTree', () => { expect(tree.getNode(10)).toBeInstanceOf(RBTreeNode); expect(tree.getNode(20)).toBeInstanceOf(RBTreeNode); expect(tree.getNode(5)).toBeInstanceOf(RBTreeNode); - expect(tree.getNode(15)).toBe(tree.NIL); + expect(tree.getNode(15)).toBe(null); }); test('should insert and find nodes with negative keys', () => { @@ -36,7 +36,7 @@ describe('RedBlackTree', () => { tree.insert(5); tree.delete(20); - expect(tree.getNode(20)).toBe(tree.NIL); + expect(tree.getNode(20)).toBe(null); }); test('should handle deleting a non-existent node', () => { @@ -45,7 +45,7 @@ describe('RedBlackTree', () => { tree.insert(5); tree.delete(15); - expect(tree.getNode(15)).toBe(tree.NIL); + expect(tree.getNode(15)).toBe(null); }); }); @@ -63,7 +63,7 @@ describe('RedBlackTree', () => { test('should handle an empty tree', () => { const minNode = tree.getLeftMost(tree.root); - expect(minNode).toBe(tree.NIL); + expect(minNode).toBe(SN); }); }); @@ -81,7 +81,7 @@ describe('RedBlackTree', () => { test('should handle an empty tree', () => { const maxNode = tree.getRightMost(tree.root); - expect(maxNode).toBe(tree.NIL); + expect(maxNode).toBe(SN); }); }); @@ -105,7 +105,7 @@ describe('RedBlackTree', () => { const node = tree.getNode(10); const successorNode = tree.getSuccessor(node); - // TODO not sure if it should be null or tree.NIL + // TODO not sure if it should be null or SN expect(successorNode).toBe(null); }); }); @@ -130,13 +130,12 @@ describe('RedBlackTree', () => { const node = tree.getNode(20); const predecessorNode = tree.getPredecessor(node); - // TODO not sure if it should be tree.NIL or something else. + // TODO not sure if it should be SN or something else. expect(predecessorNode).toBe(tree.getNode(10)); }); }); }); - describe('RedBlackTree', () => { let tree: RedBlackTree; @@ -158,7 +157,7 @@ describe('RedBlackTree', () => { tree.insert(20); tree.insert(5); tree.delete(20); - expect(tree.getNode(20)).toBe(tree.NIL); + expect(tree.getNode(20)).toBe(null); }); it('should get the successor of a node', () => { @@ -210,14 +209,15 @@ describe('RedBlackTree', () => { }); it('should fix the tree after insertion', () => { - for (let i = 0; i < 1000; i++) { - tree.insert(getRandomInt(-100, 1000)); - tree.delete(getRandomInt(-100, 1000)); - } tree.insert(1); tree.insert(2); tree.insert(5); tree.insert(15); + const node15F = tree.getNode(15); + expect(node15F.left).toBe(SN); + expect(node15F.right).toBe(SN); + expect(node15F.parent).toBe(tree.getNode(5)); + tree.insert(25); tree.insert(10); tree.insert(8); @@ -229,14 +229,50 @@ describe('RedBlackTree', () => { tree.insert(50); tree.insert(155); tree.insert(225); + const node225F = tree.getNode(225); + expect(node225F.left).toBe(SN); + expect(node225F.right).toBe(SN); + expect(node225F.parent.key).toBe(155); tree.insert(7); + + const node15S = tree.getNode(15); + expect(node15S.left.key).toBe(8); + expect(node15S.right.key).toBe(28); + expect(node15S).toBe(tree.root); + expect(node15S.parent).toBe(null); tree.delete(15); + expect(tree.root.key).toBe(22); + expect(tree.root.parent).toBe(null); + + const node15T = tree.getNode(15); + expect(node15T).toBe(null); + tree.insert(23); tree.insert(33); tree.insert(15); + const nodeLM = tree.getLeftMost(); + expect(nodeLM.key).toBe(1); - // Verify that the tree is still a valid Red-Black Tree - // You can add assertions to check the Red-Black Tree properties + const node50 = tree.getNode(50); + expect(node50.key).toBe(50); + expect(node50.left.key).toBe(33); + expect(node50.right).toBe(SN); + const node15Fo = tree.getNode(15); + + expect(node15Fo.key).toBe(15); + expect(node15Fo.left).toBe(SN); + const node225S = tree.getNode(225); + expect(node225S.left).toBe(SN); + expect(node225S.right).toBe(SN); + expect(node225S.parent.key).toBe(155); + expect(tree.getNode(0)).toBe(null); + }); + + it('should fix the tree after insertion and deletion', () => { + for (let i = 0; i < 1000; i++) { + tree.insert(getRandomInt(-100, 1000)); + tree.delete(getRandomInt(-100, 1000)); + } }); }); diff --git a/test/unit/data-structures/binary-tree/tree-multiset.test.ts b/test/unit/data-structures/binary-tree/tree-multiset.test.ts index c5c58c3..b61fdf6 100644 --- a/test/unit/data-structures/binary-tree/tree-multiset.test.ts +++ b/test/unit/data-structures/binary-tree/tree-multiset.test.ts @@ -23,10 +23,10 @@ describe('TreeMultiset operations test', () => { expect(treeMultiset.getHeight(6)).toBe(3); expect(treeMultiset.getDepth(6)).toBe(1); - const nodeId10 = treeMultiset.get(10); + const nodeId10 = treeMultiset.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = treeMultiset.get(9, node => node.value); + const nodeVal9 = treeMultiset.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); const nodesByCount1 = treeMultiset.getNodes(1, node => node.count); @@ -37,7 +37,7 @@ describe('TreeMultiset operations test', () => { const leftMost = treeMultiset.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = treeMultiset.get(15); + const node15 = treeMultiset.getNode(15); const minNodeBySpecificNode = node15 && treeMultiset.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -53,7 +53,7 @@ describe('TreeMultiset operations test', () => { const subTreeAdd = treeMultiset.subTreeTraverse((node: TreeMultisetNode) => (node.count += 1), 15); expect(subTreeAdd); } - const node11 = treeMultiset.get(11); + const node11 = treeMultiset.getNode(11); expect(node11 instanceof TreeMultisetNode); if (node11 instanceof TreeMultisetNode) { const allGreaterNodesAdded = treeMultiset.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); @@ -263,10 +263,10 @@ describe('TreeMultiset operations test recursively', () => { expect(treeMultiset.getHeight(6)).toBe(3); expect(treeMultiset.getDepth(6)).toBe(1); - const nodeId10 = treeMultiset.get(10); + const nodeId10 = treeMultiset.getNode(10); expect(nodeId10?.key).toBe(10); - const nodeVal9 = treeMultiset.get(9, node => node.value); + const nodeVal9 = treeMultiset.getNode(9, node => node.value); expect(nodeVal9?.key).toBe(9); const nodesByCount1 = treeMultiset.getNodes(1, node => node.count); @@ -277,7 +277,7 @@ describe('TreeMultiset operations test recursively', () => { const leftMost = treeMultiset.getLeftMost(); expect(leftMost?.key).toBe(1); - const node15 = treeMultiset.get(15); + const node15 = treeMultiset.getNode(15); const minNodeBySpecificNode = node15 && treeMultiset.getLeftMost(node15); expect(minNodeBySpecificNode?.key).toBe(12); @@ -293,7 +293,7 @@ describe('TreeMultiset operations test recursively', () => { const subTreeAdd = treeMultiset.subTreeTraverse((node: TreeMultisetNode) => (node.count += 1), 15); expect(subTreeAdd); } - const node11 = treeMultiset.get(11); + const node11 = treeMultiset.getNode(11); expect(node11 instanceof TreeMultisetNode); if (node11 instanceof TreeMultisetNode) { const allGreaterNodesAdded = treeMultiset.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11); diff --git a/test/utils/big-o.js b/test/utils/big-o.js index 099b7ec..5fcd405 100644 --- a/test/utils/big-o.js +++ b/test/utils/big-o.js @@ -23,9 +23,11 @@ exports.bigO = { CUBED: Math.pow(exports.magnitude.SQUARED, 3) / 1000, FACTORIAL: 10000 }; + function findPotentialN(input) { var longestArray = []; var mostProperties = {}; + function recurse(obj) { if (Array.isArray(obj)) { if (obj.length > longestArray.length) { @@ -41,6 +43,7 @@ function findPotentialN(input) { }); } } + if (Array.isArray(input)) { input.forEach(function (item) { recurse(item); @@ -51,6 +54,7 @@ function findPotentialN(input) { // return [longestArray, mostProperties] : [any[], { [key: string]: any }]; return Math.max(longestArray.length, Object.keys(mostProperties).length); } + function linearRegression(x, y) { var n = x.length; var sumX = x.reduce(function (acc, val) { @@ -87,6 +91,7 @@ function linearRegression(x, y) { var rSquared = 1 - totalVariation / explainedVariation; return {slope: slope, intercept: intercept, rSquared: rSquared}; } + function estimateBigO(runtimes, dataSizes) { // Make sure the input runtimes and data sizes have the same length if (runtimes.length !== dataSizes.length) { @@ -137,7 +142,9 @@ function estimateBigO(runtimes, dataSizes) { return complexities.join(' or '); } } + var methodLogs = new Map(); + function logBigOMetricsWrap(fn, args, fnName) { var startTime = performance.now(); var result = fn(args); @@ -169,7 +176,9 @@ function logBigOMetricsWrap(fn, args, fnName) { } return result; } + exports.logBigOMetricsWrap = logBigOMetricsWrap; + function logBigOMetrics(target, propertyKey, descriptor) { var originalMethod = descriptor.value; descriptor.value = function () { @@ -209,4 +218,5 @@ function logBigOMetrics(target, propertyKey, descriptor) { }; return descriptor; } + exports.logBigOMetrics = logBigOMetrics;