diff --git a/README.md b/README.md index 200131f..307615f 100644 --- a/README.md +++ b/README.md @@ -626,52 +626,52 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.key) // ['A', 'B', ' [//]: # (No deletion!!! Start of Replace Section)
avl-tree
-
test nametime taken (ms)executions per secsample deviation
10,000 add randomly31.3231.933.67e-4
10,000 add & delete randomly70.9014.100.00
10,000 addMany40.5824.644.87e-4
10,000 get27.3136.622.00e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 add randomly33.0930.224.32e-4
10,000 add & delete randomly74.1213.490.00
10,000 addMany41.7123.970.00
10,000 get28.3735.252.37e-4
binary-tree
-
test nametime taken (ms)executions per secsample deviation
1,000 add randomly12.3580.997.17e-5
1,000 add & delete randomly15.9862.587.98e-4
1,000 addMany10.9691.270.00
1,000 get18.6153.730.00
1,000 dfs164.206.090.04
1,000 bfs58.8417.000.01
1,000 morris256.663.907.70e-4
+
test nametime taken (ms)executions per secsample deviation
1,000 add randomly14.5068.961.33e-4
1,000 add & delete randomly16.2061.722.03e-4
1,000 addMany10.5195.128.76e-5
1,000 get18.2854.691.82e-4
1,000 dfs157.236.367.06e-4
1,000 bfs58.0617.220.01
1,000 morris256.363.900.00
bst
-
test nametime taken (ms)executions per secsample deviation
10,000 add randomly31.5931.662.74e-4
10,000 add & delete randomly74.5613.418.32e-4
10,000 addMany29.1634.300.00
10,000 get29.2434.210.00
+
test nametime taken (ms)executions per secsample deviation
10,000 add randomly30.4832.814.13e-4
10,000 add & delete randomly71.8413.920.00
10,000 addMany29.5433.855.25e-4
10,000 get30.5332.750.01
rb-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add85.8511.650.00
100,000 add & delete randomly211.544.730.00
100,000 getNode37.9226.371.65e-4
+
test nametime taken (ms)executions per secsample deviation
100,000 add90.8911.000.00
100,000 CPT add50.6519.740.00
100,000 add & delete randomly230.084.350.02
100,000 getNode38.9725.665.82e-4
100,000 add & iterator118.328.450.01
comparison
-
test nametime taken (ms)executions per secsample deviation
SRC PQ 10,000 add0.571748.734.96e-6
CJS PQ 10,000 add0.571746.694.91e-6
MJS PQ 10,000 add0.571749.684.43e-6
SRC PQ 10,000 add & pop3.47288.146.38e-4
CJS PQ 10,000 add & pop3.39295.363.90e-5
MJS PQ 10,000 add & pop3.37297.173.03e-5
+
test nametime taken (ms)executions per secsample deviation
SRC PQ 10,000 add0.146939.331.74e-6
CJS PQ 10,000 add0.156881.641.91e-6
MJS PQ 10,000 add0.571745.921.60e-5
CPT PQ 10,000 add0.571744.711.01e-5
SRC PQ 10,000 add & pop3.51284.936.79e-4
CJS PQ 10,000 add & pop3.42292.554.04e-5
MJS PQ 10,000 add & pop3.41293.385.11e-5
CPT PQ 10,000 add & pop2.09478.762.28e-5
CPT OM 100,000 add43.2223.140.00
CPT HM 10,000 set0.581721.251.85e-5
CPT HM 10,000 set & get0.681477.311.26e-5
CPT LL 1,000,000 unshift81.3812.290.02
CPT PQ 10,000 add & pop2.10476.501.60e-4
CPT DQ 1,000,000 push22.5144.420.00
CPT Q 1,000,000 push47.8520.900.01
CPT ST 1,000,000 push42.5423.510.01
CPT ST 1,000,000 push & pop50.0819.970.00
directed-graph
-
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109534.938.72e-7
1,000 addEdge6.30158.670.00
1,000 getVertex0.052.16e+43.03e-7
1,000 getEdge22.3144.820.00
tarjan210.904.740.01
tarjan all214.724.660.01
topologicalSort172.525.800.00
+
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.119501.346.10e-6
1,000 addEdge6.35157.556.69e-4
1,000 getVertex0.052.14e+42.50e-6
1,000 getEdge25.0039.990.01
tarjan219.464.560.01
tarjan all218.154.580.00
topologicalSort176.835.660.00
hash-map
-
test nametime taken (ms)executions per secsample deviation
1,000,000 set275.883.620.12
1,000,000 Map set211.664.720.01
1,000,000 Set add177.725.630.02
1,000,000 set & get317.603.150.02
1,000,000 Map set & get274.993.640.03
1,000,000 Set add & has172.235.810.02
1,000,000 ObjKey set & get929.401.080.07
1,000,000 Map ObjKey set & get310.023.230.05
1,000,000 Set ObjKey add & has283.283.530.04
+
test nametime taken (ms)executions per secsample deviation
1,000,000 set254.463.930.04
1,000,000 CPT set251.213.980.03
1,000,000 Map set211.274.730.01
1,000,000 Set add175.155.710.02
1,000,000 set & get370.542.700.11
1,000,000 CPT set & get283.343.530.07
1,000,000 Map set & get287.093.480.04
1,000,000 Set add & has190.505.250.01
1,000,000 ObjKey set & get880.471.140.10
1,000,000 Map ObjKey set & get334.472.990.05
1,000,000 Set ObjKey add & has310.123.220.06
heap
-
test nametime taken (ms)executions per secsample deviation
10,000 add & pop5.80172.358.78e-5
10,000 fib add & pop357.922.790.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add & pop80.1312.480.00
100,000 add & dfs35.0828.500.00
10,000 fib add & pop367.842.720.01
doubly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push221.574.510.03
1,000,000 unshift229.024.370.07
1,000,000 unshift & shift169.215.910.02
1,000,000 insertBefore314.483.180.07
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push237.284.210.07
1,000,000 CPT push75.6613.220.03
1,000,000 unshift226.384.420.05
1,000,000 CPT unshift93.3410.710.07
1,000,000 unshift & shift188.345.310.05
1,000,000 insertBefore329.603.030.05
singly-linked-list
-
test nametime taken (ms)executions per secsample deviation
10,000 push & pop212.984.700.01
10,000 insertBefore250.683.990.01
+
test nametime taken (ms)executions per secsample deviation
10,000 push & pop221.324.520.01
10,000 insertBefore255.523.910.01
max-priority-queue
-
test nametime taken (ms)executions per secsample deviation
10,000 refill & poll8.91112.292.26e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 refill & poll9.07110.242.71e-4
priority-queue
-
test nametime taken (ms)executions per secsample deviation
100,000 add & pop103.599.650.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add & pop101.939.817.95e-4
100,000 CPT add & pop28.5435.040.00
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push14.5568.726.91e-4
1,000,000 push & pop23.4042.735.94e-4
1,000,000 push & shift24.4140.971.45e-4
1,000,000 unshift & shift22.5644.321.30e-4
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push14.4369.292.36e-4
1,000,000 CPT push25.0839.870.01
1,000,000 push & pop22.8743.726.05e-4
1,000,000 push & shift25.2839.550.01
1,000,000 unshift & shift21.8845.712.05e-4
queue
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push39.9025.070.01
1,000,000 push & shift81.7912.230.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push38.4925.989.08e-4
1,000,000 CPT push43.9322.760.01
1,000,000 push & shift82.8512.070.00
stack
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push37.6026.600.00
1,000,000 push & pop47.0121.270.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push40.1924.880.01
1,000,000 CPT push39.8725.080.00
1,000,000 push & pop41.6724.000.01
1,000,000 CPT push & pop46.6521.440.00
trie
-
test nametime taken (ms)executions per secsample deviation
100,000 push45.9721.760.00
100,000 getWords66.2015.110.00
+
test nametime taken (ms)executions per secsample deviation
100,000 push43.4223.037.57e-4
100,000 getWords93.4110.710.00
[//]: # (No deletion!!! End of Replace Section) diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts index ed4e9b0..d26ea3f 100644 --- a/src/data-structures/binary-tree/avl-tree.ts +++ b/src/data-structures/binary-tree/avl-tree.ts @@ -11,10 +11,9 @@ import type { AVLTreeNodeNested, AVLTreeOptions, BiTreeDeleteResult, - BSTNKeyOrNode, - BTNExemplar, - BTNKey, - BTNKeyOrNode + BSTNodeKeyOrNode, + BTNodeExemplar, + BTNKey } from '../../types'; import { BTNCallback } from '../../types'; import { IBinaryTree } from '../../interfaces'; @@ -38,9 +37,9 @@ export class AVLTree = AVLTreeNode>, options?: Partial) { + constructor(elements?: Iterable>, options?: Partial) { super([], options); - if (elements) this.init(elements); + if (elements) this.addMany(elements); } /** @@ -75,9 +74,9 @@ export class AVLTree = AVLTreeNode, value?: V): N | undefined { - if (keyOrNode === null) return undefined; - const inserted = super.add(keyOrNode, value); + override add(keyOrNodeOrEntry: BTNodeExemplar): N | undefined { + if (keyOrNodeOrEntry === null) return undefined; + const inserted = super.add(keyOrNodeOrEntry); if (inserted) this._balancePath(inserted); return inserted; } @@ -116,23 +115,6 @@ export class AVLTree = AVLTreeNode>): void { - if (elements) { - for (const entryOrKey of elements) { - if (Array.isArray(entryOrKey)) { - const [key, value] = entryOrKey; - this.add(key, value); - } else { - this.add(entryOrKey); - } - } - } - } /** * The `_swap` function swaps the key, value, and height properties between two nodes in a binary @@ -144,7 +126,7 @@ export class AVLTree = AVLTreeNode, destNode: BSTNKeyOrNode): N | undefined { + protected override _swap(srcNode: BSTNodeKeyOrNode, destNode: BSTNodeKeyOrNode): N | undefined { srcNode = this.ensureNotKey(srcNode); destNode = this.ensureNotKey(destNode); diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index dc0b9ff..403b050 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -10,9 +10,10 @@ import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, - BTNExemplar, + BTNodeEntry, + BTNodeExemplar, BTNKey, - BTNKeyOrNode + BTNodeKeyOrNode } from '../../types'; import { BinaryTreeNested, @@ -131,7 +132,7 @@ export class BinaryTree = BinaryTreeNode * Creates a new instance of BinaryTree. * @param {BinaryTreeOptions} [options] - The options for the binary tree. */ - constructor(elements?: Iterable>, options?: Partial) { + constructor(elements?: Iterable>, options?: Partial) { if (options) { const { iterationType } = options; @@ -142,7 +143,7 @@ export class BinaryTree = BinaryTreeNode this._size = 0; - if (elements) this.init(elements); + if (elements) this.addMany(elements); } protected _root?: N | null; @@ -177,6 +178,10 @@ export class BinaryTree = BinaryTreeNode return new BinaryTree([], { iterationType: this.iterationType, ...options }) as TREE; } + isEntry(kne: BTNodeExemplar): kne is BTNodeEntry { + return Array.isArray(kne) && kne.length === 2; + } + /** * Time Complexity: O(n) * Space Complexity: O(1) @@ -190,7 +195,7 @@ export class BinaryTree = BinaryTreeNode * @returns The function `add` returns a node (`N`) if it was successfully inserted into the binary * tree, or `null` or `undefined` if the insertion was not successful. */ - add(keyOrNode: BTNKeyOrNode, value?: V): N | null | undefined { + add(keyOrNodeOrEntry: BTNodeExemplar): N | null | undefined { const _bfs = (root: N, newNode: N | null): N | undefined | null => { const queue = new Queue([root]); while (queue.size > 0) { @@ -208,12 +213,21 @@ export class BinaryTree = BinaryTreeNode let inserted: N | null | undefined, needInsert: N | null | undefined; - if (keyOrNode === null) { + if (keyOrNodeOrEntry === null) { needInsert = null; - } else if (this.isNodeKey(keyOrNode)) { - needInsert = this.createNode(keyOrNode, value); - } else if (keyOrNode instanceof BinaryTreeNode) { - needInsert = keyOrNode; + } else if (this.isNodeKey(keyOrNodeOrEntry)) { + needInsert = this.createNode(keyOrNodeOrEntry); + } else if (keyOrNodeOrEntry instanceof BinaryTreeNode) { + needInsert = keyOrNodeOrEntry; + } else if (this.isEntry(keyOrNodeOrEntry)) { + const [key, value] = keyOrNodeOrEntry; + if (key === undefined) { + return; + } else if (key === null) { + needInsert = null; + } else { + needInsert = this.createNode(key, value); + } } else { return; } @@ -252,19 +266,19 @@ export class BinaryTree = BinaryTreeNode * keys or nodes during the add operation. * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values. */ - addMany(keysOrNodes: (BTNKeyOrNode)[], values?: (V | undefined)[]): (N | null | undefined)[] { + addMany(nodes: Iterable>): (N | null | undefined)[] { // TODO not sure addMany not be run multi times + const keysOrNodes = [...nodes]; return keysOrNodes.map((keyOrNode, i) => { if (keyOrNode instanceof BinaryTreeNode) { - return this.add(keyOrNode.key, keyOrNode.value); + return this.add(keyOrNode); } if (keyOrNode === null) { return this.add(null); } - const value = values?.[i]; - return this.add(keyOrNode, value); + return this.add(keyOrNode); }); } @@ -285,9 +299,9 @@ export class BinaryTree = BinaryTreeNode * array. Each value in the `data` array will be assigned to the * @returns The method is returning a boolean value. */ - refill(keysOrNodes: (BTNKeyOrNode)[], values?: (V | undefined)[]): boolean { + refill(nodesOrKeysOrEntries: Iterable>): void { this.clear(); - return keysOrNodes.length === this.addMany(keysOrNodes, values).length; + this.addMany(nodesOrKeysOrEntries); } /** @@ -384,7 +398,7 @@ export class BinaryTree = BinaryTreeNode * `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot * @returns the depth of the `distNode` relative to the `beginRoot`. */ - getDepth(distNode: BTNKeyOrNode, beginRoot: BTNKeyOrNode = this.root): number { + getDepth(distNode: BTNodeKeyOrNode, beginRoot: BTNodeKeyOrNode = this.root): number { distNode = this.ensureNotKey(distNode); beginRoot = this.ensureNotKey(beginRoot); let depth = 0; @@ -417,7 +431,7 @@ export class BinaryTree = BinaryTreeNode * values: * @returns the height of the binary tree. */ - getHeight(beginRoot: BTNKeyOrNode = this.root, iterationType = this.iterationType): number { + getHeight(beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType): number { beginRoot = this.ensureNotKey(beginRoot); if (!beginRoot) return -1; @@ -466,7 +480,7 @@ export class BinaryTree = BinaryTreeNode * to calculate the minimum height of a binary tree. It can have two possible values: * @returns The function `getMinHeight` returns the minimum height of a binary tree. */ - getMinHeight(beginRoot: BTNKeyOrNode = this.root, iterationType = this.iterationType): number { + getMinHeight(beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType): number { beginRoot = this.ensureNotKey(beginRoot); if (!beginRoot) return -1; @@ -526,7 +540,7 @@ export class BinaryTree = BinaryTreeNode * value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If * @returns a boolean value. */ - isPerfectlyBalanced(beginRoot: BTNKeyOrNode = this.root): boolean { + isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode = this.root): boolean { return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot); } @@ -539,7 +553,7 @@ export class BinaryTree = BinaryTreeNode identifier: BTNKey, callback?: C, onlyOne?: boolean, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N[]; @@ -547,7 +561,7 @@ export class BinaryTree = BinaryTreeNode identifier: N | null | undefined, callback?: C, onlyOne?: boolean, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N[]; @@ -555,7 +569,7 @@ export class BinaryTree = BinaryTreeNode identifier: ReturnType, callback: C, onlyOne?: boolean, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N[]; @@ -588,7 +602,7 @@ export class BinaryTree = BinaryTreeNode identifier: ReturnType | null | undefined, callback: C = this._defaultOneParamCallback as C, onlyOne = false, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N[] { if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) @@ -636,21 +650,21 @@ export class BinaryTree = BinaryTreeNode has>( identifier: BTNKey, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): boolean; has>( identifier: N | null | undefined, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): boolean; has>( identifier: ReturnType | null | undefined, callback: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): boolean; @@ -677,7 +691,7 @@ export class BinaryTree = BinaryTreeNode has>( identifier: ReturnType | null | undefined, callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): boolean { if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) @@ -694,21 +708,21 @@ export class BinaryTree = BinaryTreeNode getNode>( identifier: BTNKey, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N | null | undefined; getNode>( identifier: N | null | undefined, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N | null | undefined; getNode>( identifier: ReturnType, callback: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): N | null | undefined; @@ -736,7 +750,7 @@ export class BinaryTree = BinaryTreeNode getNode>( identifier: ReturnType | null | undefined, callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N | null | undefined { if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) @@ -805,28 +819,28 @@ export class BinaryTree = BinaryTreeNode * @returns either the node corresponding to the given key if it is a valid node key, or the key * itself if it is not a valid node key. */ - ensureNotKey(key: BTNKeyOrNode, iterationType = IterationType.ITERATIVE): N | null | undefined { + ensureNotKey(key: BTNodeKeyOrNode, iterationType = IterationType.ITERATIVE): N | null | undefined { return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key; } get>( identifier: BTNKey, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): V | undefined; get>( identifier: N | null | undefined, callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): V | undefined; get>( identifier: ReturnType, callback: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType ): V | undefined; @@ -855,7 +869,7 @@ export class BinaryTree = BinaryTreeNode get>( identifier: ReturnType | null | undefined, callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): V | undefined { if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) @@ -899,7 +913,7 @@ export class BinaryTree = BinaryTreeNode * reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is * @returns The function `getPathToRoot` returns an array of nodes (`N[]`). */ - getPathToRoot(beginRoot: BTNKeyOrNode, isReverse = true): N[] { + getPathToRoot(beginRoot: BTNodeKeyOrNode, isReverse = true): N[] { // TODO to support get path through passing key const result: N[] = []; beginRoot = this.ensureNotKey(beginRoot); @@ -936,7 +950,7 @@ export class BinaryTree = BinaryTreeNode * is no leftmost node, it returns `null` or `undefined` depending on the input. */ getLeftMost( - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N | null | undefined { beginRoot = this.ensureNotKey(beginRoot); @@ -982,7 +996,7 @@ export class BinaryTree = BinaryTreeNode * is no rightmost node, it returns `null` or `undefined`, depending on the input. */ getRightMost( - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N | null | undefined { // TODO support get right most by passing key in @@ -1024,7 +1038,7 @@ export class BinaryTree = BinaryTreeNode * possible values: * @returns a boolean value. */ - isSubtreeBST(beginRoot: BTNKeyOrNode, iterationType = this.iterationType): boolean { + isSubtreeBST(beginRoot: BTNodeKeyOrNode, iterationType = this.iterationType): boolean { // TODO there is a bug beginRoot = this.ensureNotKey(beginRoot); if (!beginRoot) return true; @@ -1083,21 +1097,21 @@ export class BinaryTree = BinaryTreeNode subTreeTraverse>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: false ): ReturnType[]; subTreeTraverse>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: undefined ): ReturnType[]; subTreeTraverse>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: true ): ReturnType[]; @@ -1126,7 +1140,7 @@ export class BinaryTree = BinaryTreeNode */ subTreeTraverse>( callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType, includeNull = false ): ReturnType[] { @@ -1216,7 +1230,7 @@ export class BinaryTree = BinaryTreeNode dfs>( callback?: C, pattern?: DFSOrderPattern, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: false ): ReturnType[]; @@ -1224,7 +1238,7 @@ export class BinaryTree = BinaryTreeNode dfs>( callback?: C, pattern?: DFSOrderPattern, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: undefined ): ReturnType[]; @@ -1232,7 +1246,7 @@ export class BinaryTree = BinaryTreeNode dfs>( callback?: C, pattern?: DFSOrderPattern, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: true ): ReturnType[]; @@ -1263,7 +1277,7 @@ export class BinaryTree = BinaryTreeNode dfs>( callback: C = this._defaultOneParamCallback as C, pattern: DFSOrderPattern = 'in', - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType: IterationType = IterationType.ITERATIVE, includeNull = false ): ReturnType[] { @@ -1362,21 +1376,21 @@ export class BinaryTree = BinaryTreeNode bfs>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: false ): ReturnType[]; bfs>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: undefined ): ReturnType[]; bfs>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: true ): ReturnType[]; @@ -1404,7 +1418,7 @@ export class BinaryTree = BinaryTreeNode */ bfs>( callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType, includeNull = false ): ReturnType[] { @@ -1463,21 +1477,21 @@ export class BinaryTree = BinaryTreeNode listLevels>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: false ): ReturnType[][]; listLevels>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: undefined ): ReturnType[][]; listLevels>( callback?: C, - beginRoot?: BTNKeyOrNode, + beginRoot?: BTNodeKeyOrNode, iterationType?: IterationType, includeNull?: true ): ReturnType[][]; @@ -1505,7 +1519,7 @@ export class BinaryTree = BinaryTreeNode */ listLevels>( callback: C = this._defaultOneParamCallback as C, - beginRoot: BTNKeyOrNode = this.root, + beginRoot: BTNodeKeyOrNode = this.root, iterationType = this.iterationType, includeNull = false ): ReturnType[][] { @@ -1563,7 +1577,7 @@ export class BinaryTree = BinaryTreeNode * `null`, or `undefined`. * @returns The function `getPredecessor` returns a value of type `N | undefined`. */ - getPredecessor(node: BTNKeyOrNode): N | undefined { + getPredecessor(node: BTNodeKeyOrNode): N | undefined { node = this.ensureNotKey(node); if (!this.isRealNode(node)) return undefined; @@ -1623,7 +1637,7 @@ export class BinaryTree = BinaryTreeNode morris>( callback: C = this._defaultOneParamCallback as C, pattern: DFSOrderPattern = 'in', - beginRoot: BTNKeyOrNode = this.root + beginRoot: BTNodeKeyOrNode = this.root ): ReturnType[] { beginRoot = this.ensureNotKey(beginRoot); if (beginRoot === null) return []; @@ -1735,7 +1749,7 @@ export class BinaryTree = BinaryTreeNode const newTree = this.createTree(); for (const [key, value] of this) { if (predicate([key, value], this)) { - newTree.add(key, value); + newTree.add([key, value]); } } return newTree; @@ -1750,7 +1764,7 @@ export class BinaryTree = BinaryTreeNode map(callback: (entry: [BTNKey, V | undefined], tree: this) => V) { const newTree = this.createTree(); for (const [key, value] of this) { - newTree.add(key, callback([key, value], this)); + newTree.add([key, callback([key, value], this)]); } return newTree; } @@ -1831,7 +1845,7 @@ export class BinaryTree = BinaryTreeNode * following types: * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes. */ - print(beginRoot: BTNKeyOrNode = this.root, options?: BinaryTreePrintOptions): void { + print(beginRoot: BTNodeKeyOrNode = this.root, options?: BinaryTreePrintOptions): void { const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options }; beginRoot = this.ensureNotKey(beginRoot); if (!beginRoot) return; @@ -1853,19 +1867,6 @@ export class BinaryTree = BinaryTreeNode display(beginRoot); } - init(elements: Iterable>): void { - if (elements) { - for (const entryOrKey of elements) { - if (Array.isArray(entryOrKey)) { - const [key, value] = entryOrKey; - this.add(key, value); - } else { - this.add(entryOrKey); - } - } - } - } - protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout { const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options; const emptyDisplayLayout = [['─'], 1, 0, 0]; @@ -1924,7 +1925,7 @@ export class BinaryTree = BinaryTreeNode * @param {N} destNode - The destination node to swap. * @returns {N} - The destination node after the swap. */ - protected _swap(srcNode: BTNKeyOrNode, destNode: BTNKeyOrNode): N | undefined { + protected _swap(srcNode: BTNodeKeyOrNode, destNode: BTNodeKeyOrNode): N | undefined { srcNode = this.ensureNotKey(srcNode); destNode = this.ensureNotKey(destNode); @@ -1956,7 +1957,7 @@ export class BinaryTree = BinaryTreeNode * the binary tree. If neither the left nor right child is available, the function returns undefined. * If the parent node is null, the function also returns undefined. */ - protected _addTo(newNode: N | null | undefined, parent: BTNKeyOrNode): N | null | undefined { + protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode): N | null | undefined { if (this.isNodeKey(parent)) parent = this.getNode(parent); if (parent) { diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 64f9aa1..d805937 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -7,14 +7,14 @@ */ import type { BSTNested, - BSTNKeyOrNode, + BSTNodeKeyOrNode, BSTNodeNested, BSTOptions, BTNCallback, - BTNExemplar, + BTNodeExemplar, BTNKey, - BTNKeyOrNode, - Comparator + Comparator, + BTNodePureExemplar } from '../../types'; import { CP, IterationType } from '../../types'; import { BinaryTree, BinaryTreeNode } from './binary-tree'; @@ -76,12 +76,8 @@ export class BST = BSTNode> extends BinaryTree implements IBinaryTree { - /** - * The constructor function initializes a binary search tree with an optional comparator function. - * @param {BSTOptions} [options] - An optional object that contains additional configuration options - * for the binary search tree. - */ - constructor(elements?: Iterable>, options?: Partial) { + + constructor(elements?: Iterable>, options?: Partial) { super([], options); if (options) { @@ -92,7 +88,8 @@ export class BST = BSTNode> } this._root = undefined; - if (elements) this.init(elements); + + if (elements) this.addMany(elements); } protected override _root?: N; @@ -137,15 +134,23 @@ export class BST = BSTNode> * @returns The method `add` returns a node (`N`) that was inserted into the binary search tree. If * no node was inserted, it returns `undefined`. */ - override add(keyOrNode: BTNKeyOrNode, value?: V): N | undefined { - if (keyOrNode === null) return undefined; + override add(keyOrNodeOrEntry: BTNodeExemplar): N | undefined { + if (keyOrNodeOrEntry === null) return undefined; // TODO support node as a parameter let inserted: N | undefined; let newNode: N | undefined; - if (keyOrNode instanceof BSTNode) { - newNode = keyOrNode; - } else if (this.isNodeKey(keyOrNode)) { - newNode = this.createNode(keyOrNode, value); + if (keyOrNodeOrEntry instanceof BSTNode) { + newNode = keyOrNodeOrEntry; + } else if (this.isNodeKey(keyOrNodeOrEntry)) { + newNode = this.createNode(keyOrNodeOrEntry); + } else if (this.isEntry(keyOrNodeOrEntry)) { + const [key, value] = keyOrNodeOrEntry; + if (key === undefined || key === null) { + return; + } else { + newNode = this.createNode(key, value); + + } } else { newNode = undefined; } @@ -230,57 +235,55 @@ export class BST = BSTNode> * @returns The function `addMany` returns an array of nodes (`N`) or `undefined` values. */ override addMany( - keysOrNodes: (BSTNKeyOrNode)[], - data?: (V | undefined)[], + keysOrNodesOrEntries: Iterable>, isBalanceAdd = true, iterationType = this.iterationType ): (N | undefined)[] { + const inserted: (N | undefined)[] = [] + if (!isBalanceAdd) { + for (const kve of keysOrNodesOrEntries) { + const nn = this.add(kve) + inserted.push(nn); + } + return inserted; + } + const realBTNExemplars: BTNodePureExemplar[] = []; + + + const isRealBTNExemplar = (kve: BTNodeExemplar): kve is BTNodePureExemplar => { + if (kve === undefined || kve === null) return false; + return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null)); + } + + for (const kve of keysOrNodesOrEntries) { + isRealBTNExemplar(kve) && realBTNExemplars.push(kve); + } + // TODO this addMany function is inefficient, it should be optimized - function hasNoUndefined(arr: (BSTNKeyOrNode)[]): arr is (BTNKey | N)[] { - return arr.indexOf(undefined) === -1; - } + let sorted: BTNodePureExemplar[] = []; - if (!isBalanceAdd || !hasNoUndefined(keysOrNodes)) { - return super.addMany(keysOrNodes, data).map(n => n ?? undefined); - } + sorted = realBTNExemplars.sort((a, b) => { + let aR: number, bR: number; + if (this.isEntry(a)) aR = a[0] + else if (this.isRealNode(a)) aR = a.key + else aR = a; - const inserted: (N | undefined)[] = []; - const combinedArr: [BTNKey | N, V][] = keysOrNodes.map( - (value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V] - ); + if (this.isEntry(b)) bR = b[0] + else if (this.isRealNode(b)) bR = b.key + else bR = b; - let sorted = []; + return aR - bR; + }) - function _isNodeOrUndefinedTuple(arr: [BTNKey | N, V][]): arr is [N, V][] { - for (const [keyOrNode] of arr) if (keyOrNode instanceof BSTNode) return true; - return false; - } - const _isBinaryTreeKeyOrNullTuple = (arr: [BTNKey | N, V][]): arr is [BTNKey, V][] => { - for (const [keyOrNode] of arr) if (this.isNodeKey(keyOrNode)) return true; - return false; - }; - - let sortedKeysOrNodes: (number | N | undefined)[] = [], - sortedData: (V | undefined)[] | undefined = []; - - if (_isNodeOrUndefinedTuple(combinedArr)) { - sorted = combinedArr.sort((a, b) => a[0].key - b[0].key); - } else if (_isBinaryTreeKeyOrNullTuple(combinedArr)) { - sorted = combinedArr.sort((a, b) => a[0] - b[0]); - } else { - throw new Error('Invalid input keysOrNodes'); - } - sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode); - sortedData = sorted.map(([, value]) => value); - const _dfs = (arr: (BSTNKeyOrNode)[], data?: (V | undefined)[]) => { + const _dfs = (arr: BTNodePureExemplar[]) => { if (arr.length === 0) return; const mid = Math.floor((arr.length - 1) / 2); - const newNode = this.add(arr[mid], data?.[mid]); + const newNode = this.add(arr[mid]); inserted.push(newNode); - _dfs(arr.slice(0, mid), data?.slice(0, mid)); - _dfs(arr.slice(mid + 1), data?.slice(mid + 1)); + _dfs(arr.slice(0, mid)); + _dfs(arr.slice(mid + 1)); }; const _iterate = () => { const n = sorted.length; @@ -291,7 +294,7 @@ export class BST = BSTNode> const [l, r] = popped; if (l <= r) { const m = l + Math.floor((r - l) / 2); - const newNode = this.add(sortedKeysOrNodes[m], sortedData?.[m]); + const newNode = this.add(realBTNExemplars[m]); inserted.push(newNode); stack.push([m + 1, r]); stack.push([l, m - 1]); @@ -300,7 +303,7 @@ export class BST = BSTNode> } }; if (iterationType === IterationType.RECURSIVE) { - _dfs(sortedKeysOrNodes, sortedData); + _dfs(sorted); } else { _iterate(); } @@ -328,7 +331,7 @@ export class BST = BSTNode> * the key of the leftmost node if the comparison result is greater than, and the key of the * rightmost node otherwise. If no node is found, it returns 0. */ - lastKey(beginRoot: BSTNKeyOrNode = this.root, iterationType = this.iterationType): BTNKey { + lastKey(beginRoot: BSTNodeKeyOrNode = this.root, iterationType = this.iterationType): BTNKey { if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0; else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0; else return this.getRightMost(beginRoot, iterationType)?.key ?? 0; @@ -392,7 +395,7 @@ export class BST = BSTNode> * type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`. * @returns either a node object (N) or undefined. */ - override ensureNotKey(key: BSTNKeyOrNode, iterationType = IterationType.ITERATIVE): N | undefined { + override ensureNotKey(key: BSTNodeKeyOrNode, iterationType = IterationType.ITERATIVE): N | undefined { return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key; } @@ -423,7 +426,7 @@ export class BST = BSTNode> identifier: ReturnType | undefined, callback: C = this._defaultOneParamCallback as C, onlyOne = false, - beginRoot: BSTNKeyOrNode = this.root, + beginRoot: BSTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N[] { beginRoot = this.ensureNotKey(beginRoot); @@ -504,7 +507,7 @@ export class BST = BSTNode> lesserOrGreaterTraverse>( callback: C = this._defaultOneParamCallback as C, lesserOrGreater: CP = CP.lt, - targetNode: BSTNKeyOrNode = this.root, + targetNode: BSTNodeKeyOrNode = this.root, iterationType = this.iterationType ): ReturnType[] { targetNode = this.ensureNotKey(targetNode); @@ -569,7 +572,7 @@ export class BST = BSTNode> if (l > r) return; const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; - this.add(midNode.key, midNode.value); + this.add([midNode.key, midNode.value]); buildBalanceBST(l, m - 1); buildBalanceBST(m + 1, r); }; @@ -586,7 +589,7 @@ export class BST = BSTNode> const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; debugger; - this.add(midNode.key, midNode.value); + this.add([midNode.key, midNode.value]); stack.push([m + 1, r]); stack.push([l, m - 1]); } @@ -664,23 +667,6 @@ export class BST = BSTNode> return balanced; } - /** - * Time Complexity: O(n) - Visiting each node once. - * Space Complexity: O(log n) - Space for the recursive call stack in the worst case. - */ - - override init(elements: Iterable>): void { - if (elements) { - for (const entryOrKey of elements) { - if (Array.isArray(entryOrKey)) { - const [key, value] = entryOrKey; - this.add(key, value); - } else { - this.add(entryOrKey); - } - } - } - } protected _setRoot(v: N | undefined) { if (v) { diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 2b6e23b..ac11c78 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -8,11 +8,10 @@ import { BiTreeDeleteResult, - BSTNKeyOrNode, + BSTNodeKeyOrNode, BTNCallback, - BTNExemplar, + BTNodeExemplar, BTNKey, - BTNKeyOrNode, IterationType, RBTNColor, RBTreeOptions, @@ -53,11 +52,11 @@ export class RedBlackTree = RedBlackTr * @param {RBTreeOptions} [options] - The `options` parameter is an optional object that can be * passed to the constructor. It is used to configure the RBTree object with specific options. */ - constructor(elements?: Iterable>, options?: Partial) { + constructor(elements?: Iterable>, options?: Partial) { super([], options); this._root = this.Sentinel; - if (elements) this.init(elements); + if (elements) this.addMany(elements); } protected _root: N; @@ -94,16 +93,21 @@ export class RedBlackTree = RedBlackTr * key in the node being added to the Red-Black Tree. * @returns The method returns either a node (`N`) or `undefined`. */ - override add(keyOrNode: BTNKeyOrNode, value?: V): N | undefined { + override add(keyOrNodeOrEntry: BTNodeExemplar): N | undefined { let node: N; - if (this.isNodeKey(keyOrNode)) { - node = this.createNode(keyOrNode, value, RBTNColor.RED); - } else if (keyOrNode instanceof RedBlackTreeNode) { - node = keyOrNode; - } else if (keyOrNode === null) { - return; - } else if (keyOrNode === undefined) { + if (this.isNodeKey(keyOrNodeOrEntry)) { + node = this.createNode(keyOrNodeOrEntry, undefined, RBTNColor.RED); + } else if (keyOrNodeOrEntry instanceof RedBlackTreeNode) { + node = keyOrNodeOrEntry; + } else if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) { return; + } else if (this.isEntry(keyOrNodeOrEntry)) { + const [key, value] = keyOrNodeOrEntry; + if (key === undefined || key === null) { + return; + } else { + node = this.createNode(key, value, RBTNColor.RED); + } } else { return; } @@ -287,7 +291,7 @@ export class RedBlackTree = RedBlackTr getNode>( identifier: ReturnType | undefined, callback: C = this._defaultOneParamCallback as C, - beginRoot: BSTNKeyOrNode = this.root, + beginRoot: BSTNodeKeyOrNode = this.root, iterationType = this.iterationType ): N | null | undefined { if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; @@ -359,19 +363,6 @@ export class RedBlackTree = RedBlackTr this._size = 0; } - init(elements: Iterable>): void { - if (elements) { - for (const entryOrKey of elements) { - if (Array.isArray(entryOrKey)) { - const [key, value] = entryOrKey; - this.add(key, value); - } else { - this.add(entryOrKey); - } - } - } - } - protected override _setRoot(v: N) { if (v) { v.parent = undefined; diff --git a/src/data-structures/binary-tree/tree-multimap.ts b/src/data-structures/binary-tree/tree-multimap.ts index d9ffffb..a9e564d 100644 --- a/src/data-structures/binary-tree/tree-multimap.ts +++ b/src/data-structures/binary-tree/tree-multimap.ts @@ -5,14 +5,7 @@ * @copyright Copyright (c) 2022 Tyler Zeng * @license MIT License */ -import type { - BSTNKeyOrNode, - BTNExemplar, - BTNKey, - BTNKeyOrNode, - TreeMultimapNodeNested, - TreeMultimapOptions -} from '../../types'; +import type { BSTNodeKeyOrNode, BTNodeExemplar, BTNKey, TreeMultimapNodeNested, TreeMultimapOptions } from '../../types'; import { BiTreeDeleteResult, BTNCallback, CP, FamilyPosition, IterationType, TreeMultimapNested } from '../../types'; import { IBinaryTree } from '../../interfaces'; import { AVLTree, AVLTreeNode } from './avl-tree'; @@ -53,15 +46,18 @@ export class TreeMultimap = TreeMultim * @param {TreeMultimapOptions} [options] - An optional object that contains additional configuration options for the * TreeMultimap. */ - constructor(elements?: Iterable>, options?: Partial) { + constructor(elements?: Iterable>, options?: Partial) { super([], options); - if (elements) this.init(elements); + if (elements) this.addMany(elements); } private _count = 0; + // TODO the _count is not accurate after nodes count modified get count(): number { - return this._count; + let sum = 0; + this.subTreeTraverse(node => sum += node.count); + return sum; } /** @@ -98,17 +94,28 @@ export class TreeMultimap = TreeMultim * times the key-value pair should be added to the multimap. If not provided, the default value is 1. * @returns a node (`N`) or `undefined`. */ - override add(keyOrNode: BTNKeyOrNode, value?: V, count = 1): N | undefined { - if (keyOrNode === null) return undefined; + override add(keyOrNodeOrEntry: BTNodeExemplar, count = 1): N | undefined { + if (keyOrNodeOrEntry === null) return; let inserted: N | undefined = undefined, newNode: N | undefined; - if (keyOrNode instanceof TreeMultimapNode) { - newNode = this.createNode(keyOrNode.key, keyOrNode.value, keyOrNode.count); - } else if (keyOrNode === undefined) { - newNode = undefined; + if (keyOrNodeOrEntry instanceof TreeMultimapNode) { + newNode = this.createNode(keyOrNodeOrEntry.key, keyOrNodeOrEntry.value, keyOrNodeOrEntry.count); + } else if (keyOrNodeOrEntry === undefined) { + return; + } else if (this.isEntry(keyOrNodeOrEntry)) { + const [key, value] = keyOrNodeOrEntry; + if (key === null || key === undefined) { + return + } else { + newNode = this.createNode(key, value, count); + } + } else if (typeof keyOrNodeOrEntry === 'number') { + newNode = this.createNode(keyOrNodeOrEntry, undefined, 1); } else { - newNode = this.createNode(keyOrNode, value, count); + + return } + if (!this.root) { this._setRoot(newNode); this._size = this.size + 1; @@ -185,23 +192,22 @@ export class TreeMultimap = TreeMultim * TreeMultimap. If provided, the length of the `data` array should be the same as the length of the * @returns The function `addMany` returns an array of nodes (`N`) or `undefined` values. */ - override addMany(keysOrNodes: (BSTNKeyOrNode)[], data?: V[]): (N | undefined)[] { + override addMany(keysOrNodesOrEntries: Iterable>): (N | undefined)[] { const inserted: (N | undefined)[] = []; - for (let i = 0; i < keysOrNodes.length; i++) { - const keyOrNode = keysOrNodes[i]; + for (const keyOrNode of keysOrNodesOrEntries) { if (keyOrNode instanceof TreeMultimapNode) { - inserted.push(this.add(keyOrNode.key, keyOrNode.value, keyOrNode.count)); + inserted.push(this.add(keyOrNode, keyOrNode.count)); continue; } - if (keyOrNode === undefined) { - inserted.push(this.add(NaN, undefined, 0)); + if (keyOrNode === undefined || keyOrNode === null) { + inserted.push(this.add(NaN, 0)); continue; } - inserted.push(this.add(keyOrNode, data?.[i], 1)); + inserted.push(this.add(keyOrNode, 1)); } return inserted; } @@ -234,7 +240,7 @@ export class TreeMultimap = TreeMultim if (l > r) return; const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; - this.add(midNode.key, midNode.value, midNode.count); + this.add([midNode.key, midNode.value], midNode.count); buildBalanceBST(l, m - 1); buildBalanceBST(m + 1, r); }; @@ -250,7 +256,7 @@ export class TreeMultimap = TreeMultim if (l <= r) { const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; - this.add(midNode.key, midNode.value, midNode.count); + this.add([midNode.key, midNode.value], midNode.count); stack.push([m + 1, r]); stack.push([l, m - 1]); } @@ -357,24 +363,6 @@ export class TreeMultimap = TreeMultim this._count = 0; } - /** - * Time Complexity: O(log n) - logarithmic time, where "n" is the number of nodes in the tree. The delete method of the superclass (AVLTree) has logarithmic time complexity. - * Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size. - */ - - init(elements: Iterable>): void { - if (elements) { - for (const entryOrKey of elements) { - if (Array.isArray(entryOrKey)) { - const [key, value] = entryOrKey; - this.add(key, value); - } else { - this.add(entryOrKey); - } - } - } - } - /** * Time Complexity: O(1) - constant time, as it performs basic pointer assignments. * Space Complexity: O(1) - constant space, as it only uses a constant amount of memory. @@ -390,7 +378,7 @@ export class TreeMultimap = TreeMultim * @returns The method `_addTo` returns either the `parent.left` or `parent.right` node that was * added, or `undefined` if no node was added. */ - protected override _addTo(newNode: N | undefined, parent: BSTNKeyOrNode): N | undefined { + protected override _addTo(newNode: N | undefined, parent: BSTNodeKeyOrNode): N | undefined { parent = this.ensureNotKey(parent); if (parent) { if (parent.left === undefined) { @@ -425,7 +413,7 @@ export class TreeMultimap = TreeMultim * @returns either the `destNode` object if both `srcNode` and `destNode` are defined, or `undefined` * if either `srcNode` or `destNode` is undefined. */ - protected _swap(srcNode: BSTNKeyOrNode, destNode: BSTNKeyOrNode): N | undefined { + protected _swap(srcNode: BSTNodeKeyOrNode, destNode: BSTNodeKeyOrNode): N | undefined { srcNode = this.ensureNotKey(srcNode); destNode = this.ensureNotKey(destNode); if (srcNode && destNode) { diff --git a/src/interfaces/binary-tree.ts b/src/interfaces/binary-tree.ts index 589811d..5615c3b 100644 --- a/src/interfaces/binary-tree.ts +++ b/src/interfaces/binary-tree.ts @@ -5,7 +5,7 @@ import { BinaryTreeOptions, BiTreeDeleteResult, BTNCallback, - BTNExemplar, + BTNodeExemplar, BTNKey, } from '../types'; @@ -14,9 +14,9 @@ export interface IBinaryTree = BinaryTre createTree(options?: Partial): TREE; - init(elements: Iterable>): void; + add(keyOrNodeOrEntry: BTNodeExemplar, count?: number): N | null | undefined; - add(keyOrNode: BTNKey | N | null, value?: N['value']): N | null | undefined; + addMany(nodes: Iterable>): (N | null | undefined)[]; delete>(identifier: ReturnType | null, callback: C): BiTreeDeleteResult[]; } diff --git a/src/types/common.ts b/src/types/common.ts index c6c760c..3e6b636 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -24,8 +24,14 @@ export type IterableWithSizeOrLength = IterableWithSize | IterableWithLeng export type BinaryTreePrintOptions = { isShowUndefined?: boolean, isShowNull?: boolean, isShowRedBlackNIL?: boolean } -export type BTNExemplar = [BTNKey | null | undefined, T | undefined] | BTNKeyOrNode +export type BTNodeEntry = [BTNKey | null | undefined, T | undefined]; -export type BTNKeyOrNode = BTNKey | null | undefined | N; +export type BTNodeKeyOrNode = BTNKey | null | undefined | N; -export type BSTNKeyOrNode = BTNKey | undefined | N; \ No newline at end of file +export type BTNodeExemplar = BTNodeEntry | BTNodeKeyOrNode + +export type BTNodePureExemplar = [BTNKey, T | undefined] | BTNodePureKeyOrNode + +export type BTNodePureKeyOrNode = BTNKey | N; + +export type BSTNodeKeyOrNode = BTNKey | undefined | N; \ No newline at end of file diff --git a/test/performance/data-structures/comparison/comparison.test.ts b/test/performance/data-structures/comparison/comparison.test.ts index 988f2d1..89253f9 100644 --- a/test/performance/data-structures/comparison/comparison.test.ts +++ b/test/performance/data-structures/comparison/comparison.test.ts @@ -34,7 +34,7 @@ suite }) .add(`MJS PQ ${TEN_THOUSAND.toLocaleString()} add`, () => { - const pq = new MJSPriorityQueue([],{ comparator: (a, b) => b - a }); + const pq = new MJSPriorityQueue([], { comparator: (a, b) => b - a }); for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i); }); @@ -54,13 +54,13 @@ suite for (let i = 0; i < TEN_THOUSAND; i++) pq.pop(); }) .add(`CJS PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => { - const pq = new CJSPriorityQueue([],{ comparator: (a, b) => b - a }); + const pq = new CJSPriorityQueue([], { comparator: (a, b) => b - a }); for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i); for (let i = 0; i < TEN_THOUSAND; i++) pq.pop(); }) .add(`MJS PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => { - const pq = new MJSPriorityQueue([],{ comparator: (a, b) => b - a }); + const pq = new MJSPriorityQueue([], { comparator: (a, b) => b - a }); for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i); for (let i = 0; i < TEN_THOUSAND; i++) pq.pop(); 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 2a31c59..be18fd3 100644 --- a/test/unit/data-structures/binary-tree/avl-tree.test.ts +++ b/test/unit/data-structures/binary-tree/avl-tree.test.ts @@ -5,7 +5,7 @@ describe('AVL Tree Test', () => { const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; const tree = new AVLTree(); - for (const i of arr) tree.add(i, i); + for (const i of arr) tree.add([i, i]); tree.add(null); const node6 = tree.getNode(6); @@ -114,7 +114,7 @@ describe('AVL Tree Test recursively', () => { const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; const tree = new AVLTree([], { iterationType: IterationType.RECURSIVE }); - for (const i of arr) tree.add(i, i); + for (const i of arr) tree.add([i, i]); const node6 = tree.getNode(6); @@ -230,7 +230,7 @@ describe('AVLTree APIs test', () => { avl.add(node2); const node3 = new AVLTreeNode(3, { id: 3, text: 'text3' }); avl.add(node3); - avl.add(node3, { id: 3, text: 'text33' }); + avl.add([3, { id: 3, text: 'text33' }]); const bfsRes = avl.bfs(node => node.key); expect(bfsRes[0]).toBe(2); @@ -240,26 +240,26 @@ describe('AVLTree APIs test', () => { describe('AVLTree', () => { it('should balance the tree using _balanceLR when nodes are added', () => { const avlTree = new AVLTree(); - avlTree.add(10, 'A'); - avlTree.add(5, 'B'); - avlTree.add(15, 'C'); - avlTree.add(3, 'D'); - avlTree.add(7, 'E'); + avlTree.add([10, 'A']); + avlTree.add([5, 'B']); + avlTree.add([15, 'C']); + avlTree.add([3, 'D']); + avlTree.add([7, 'E']); // Adding nodes to trigger _balanceLR - avlTree.add(12, 'F'); + avlTree.add([12, 'F']); // You can add more specific assertions to check the tree's balance and structure. }); it('should balance the tree using _balanceLR when nodes are deleted', () => { const avlTree = new AVLTree(); - avlTree.add(10, 'A'); - avlTree.add(5, 'B'); - avlTree.add(15, 'C'); - avlTree.add(3, 'D'); - avlTree.add(7, 'E'); - avlTree.add(12, 'F'); + avlTree.add([10, 'A']); + avlTree.add([5, 'B']); + avlTree.add([15, 'C']); + avlTree.add([3, 'D']); + avlTree.add([7, 'E']); + avlTree.add([12, 'F']); // Deleting nodes to trigger _balanceLR avlTree.delete(3); @@ -279,7 +279,7 @@ describe('AVLTree', () => { avl.add(node2); const node3 = new AVLTreeNode(3, { id: 3, text: 'text3' }); avl.add(node3); - avl.add(node3, { id: 3, text: 'text33' }); + avl.add([3, { id: 3, text: 'text33' }]); const bfsRes = avl.bfs(node => node); expect(bfsRes[0]?.key).toBe(2); @@ -291,9 +291,9 @@ describe('AVLTree iterative methods test', () => { let avl: AVLTree; beforeEach(() => { avl = new AVLTree(); - avl.add(1, 'a'); - avl.add(2, 'b'); - avl.add(3, 'c'); + avl.add([1, 'a']); + avl.add([2, 'b']); + avl.add([3, 'c']); }); test('The node obtained by get Node should match the node type', () => { 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 b4f2f60..ab9d434 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -1,6 +1,5 @@ -import { BinaryTree, BinaryTreeNode, IterationType } from '../../../../src'; +import { BinaryTree, BinaryTreeNode, FamilyPosition, IterationType } from '../../../../src'; import { getRandomIntArray } from '../../../utils'; -import { FamilyPosition } from 'binary-tree-typed'; // import {isDebugTest} from '../../../config'; // const isDebug = isDebugTest; @@ -137,10 +136,10 @@ describe('BinaryTree', () => { }); it('should add and find nodes', () => { - tree.add(1, 1); + tree.add([1, 1]); tree.add(undefined); - tree.add(2, 2); - tree.add(3, 3); + tree.add([2, 2]); + tree.add([3, 3]); expect(tree.has(1)).toBe(true); expect(tree.has(2)).toBe(true); @@ -395,9 +394,9 @@ describe('BinaryTree', () => { }); it('should add nodes to the tree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); expect(tree.size).toBe(3); expect(tree.isEmpty()).toBe(false); @@ -405,9 +404,9 @@ describe('BinaryTree', () => { }); it('should clear the BinaryTree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); tree.clear(); @@ -417,9 +416,9 @@ describe('BinaryTree', () => { }); it('should get nodes by key', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); const nodeA = tree.getNode(5); const nodeB = tree.getNode(3); @@ -431,7 +430,7 @@ describe('BinaryTree', () => { }); it('should return null when getting a non-existent node', () => { - tree.add(5, 'A'); + tree.add([5, 'A']); const node = tree.getNode(3); @@ -439,18 +438,18 @@ describe('BinaryTree', () => { }); it('should get the depth of a node', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); expect(tree.getDepth(7)).toBe(1); expect(tree.getDepth(3)).toBe(1); }); it('should get the height of the tree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); expect(tree.getHeight()).toBe(1); expect(tree.getHeight(undefined, IterationType.RECURSIVE)).toBe(1); @@ -458,17 +457,17 @@ describe('BinaryTree', () => { }); it('should check if the tree is a binary search tree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); expect(tree.isBST()).toBe(true); }); it('should perform a depth-first traversal', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); const result = tree.dfs(); expect(result).toEqual([3, 5, 7]); @@ -476,9 +475,9 @@ describe('BinaryTree', () => { }); it('should perform a breadth-first traversal', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); const result = tree.bfs(node => node.key); expect(result).toEqual([5, 3, 7]); @@ -486,9 +485,9 @@ describe('BinaryTree', () => { }); it('should list levels of the tree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); const levels = tree.listLevels(); expect(levels).toEqual([[5], [3, 7]]); @@ -496,9 +495,9 @@ describe('BinaryTree', () => { }); it('should delete nodes from the tree', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); tree.delete(3); @@ -507,17 +506,17 @@ describe('BinaryTree', () => { }); it('should check if the tree is perfectly balanced', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); expect(tree.isPerfectlyBalanced()).toBe(true); }); it('should get nodes by a custom callback', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); const nodes = tree.getNodes('B', (node: BinaryTreeNode) => node.value); @@ -537,9 +536,9 @@ describe('BinaryTree', () => { }); it('should perform Morris traversal', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); tree.iterationType = IterationType.ITERATIVE; expect([...tree]).toEqual([[3, "B"], [5, "A"], [7, "C"]]); @@ -553,9 +552,9 @@ describe('BinaryTree', () => { }); it('should perform delete all', () => { - tree.add(5, 'A'); - tree.add(3, 'B'); - tree.add(7, 'C'); + tree.add([5, 'A']); + tree.add([3, 'B']); + tree.add([7, 'C']); tree.delete(5); tree.delete(7); @@ -570,9 +569,9 @@ describe('BinaryTree iterative methods test', () => { let binaryTree: BinaryTree; beforeEach(() => { binaryTree = new BinaryTree(); - binaryTree.add(1, 'a'); - binaryTree.add(2, 'b'); - binaryTree.add(3, 'c'); + binaryTree.add([1, 'a']); + binaryTree.add([2, 'b']); + binaryTree.add([3, 'c']); }); test('The node obtained by get Node should match the node type', () => { diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index 20e513d..981aa16 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -7,10 +7,10 @@ describe('BST operations test', () => { it('should perform various operations on a Binary Search Tree with numeric values', () => { const bst = new BST(); expect(bst).toBeInstanceOf(BST); - bst.add(11, 11); - bst.add(3, 3); - const idsAndValues = [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; - bst.addMany(idsAndValues, idsAndValues, false); + bst.add([11, 11]); + bst.add([3, 3]); + const idsAndValues: [number, number][] = [[15, 15], [1, 1], [8, 8], [13, 13], [16, 16], [2, 2], [6, 6], [9, 9], [12, 12], [14, 14], [4, 4], [7, 7], [10, 10], [5, 5]]; + bst.addMany(idsAndValues, false); expect(bst.root).toBeInstanceOf(BSTNode); if (bst.root) expect(bst.root.key).toBe(11); @@ -191,30 +191,26 @@ describe('BST operations test', () => { it('should perform various operations on a Binary Search Tree with object values', () => { const objBST = new BST<{ key: number; keyA: number }>(); expect(objBST).toBeInstanceOf(BST); - objBST.add(11, { key: 11, keyA: 11 }); - objBST.add(3, { key: 3, keyA: 3 }); - const values = [ - { key: 15, keyA: 15 }, - { key: 1, keyA: 1 }, - { key: 8, keyA: 8 }, - { key: 13, keyA: 13 }, - { key: 16, keyA: 16 }, - { key: 2, keyA: 2 }, - { key: 6, keyA: 6 }, - { key: 9, keyA: 9 }, - { key: 12, keyA: 12 }, - { key: 14, keyA: 14 }, - { key: 4, keyA: 4 }, - { key: 7, keyA: 7 }, - { key: 10, keyA: 10 }, - { key: 5, keyA: 5 } + objBST.add([11, { key: 11, keyA: 11 }]); + objBST.add([3, { key: 3, keyA: 3 }]); + const values: [number, { key: number; keyA: number }][] = [ + [15, { key: 15, keyA: 15 }], + [1, { key: 1, keyA: 1 }], + [8, { key: 8, keyA: 8 }], + [13, { key: 13, keyA: 13 }], + [16, { key: 16, keyA: 16 }], + [2, { key: 2, keyA: 2 }], + [6, { key: 6, keyA: 6 }], + [9, { key: 9, keyA: 9 }], + [12, { key: 12, keyA: 12 }], + [14, { key: 14, keyA: 14 }], + [4, { key: 4, keyA: 4 }], + [7, { key: 7, keyA: 7 }], + [10, { key: 10, keyA: 10 }], + [5, { key: 5, keyA: 5 }] ]; - objBST.addMany( - values.map(item => item.key), - values, - false - ); + objBST.addMany(values, false); expect(objBST.root).toBeInstanceOf(BSTNode); @@ -395,12 +391,12 @@ describe('BST operations test', () => { describe('BST operations test recursively', () => { it('should perform various operations on a Binary Search Tree with numeric values', () => { - const bst = new BST([], { iterationType: IterationType.RECURSIVE }); + const bst = new BST([], { iterationType: IterationType.RECURSIVE }); expect(bst).toBeInstanceOf(BST); - bst.add(11, 11); - bst.add(3, 3); + bst.add([11, 11]); + bst.add([3, 3]); const idsAndValues = [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; - bst.addMany(idsAndValues, idsAndValues, false); + bst.addMany(idsAndValues, false); expect(bst.root).toBeInstanceOf(BSTNode); if (bst.root) expect(bst.root.key).toBe(11); @@ -414,11 +410,11 @@ describe('BST operations test recursively', () => { expect(node6 && bst.getDepth(6)).toBe(3); const nodeId10 = bst.getNode(10); - expect(bst.get(10)).toBe(10); + expect(bst.get(10)).toBe(undefined); expect(nodeId10?.key).toBe(10); const nodeVal9 = bst.getNode(9, node => node.value); - expect(nodeVal9?.key).toBe(9); + expect(nodeVal9?.key).toBe(undefined); const leftMost = bst.getLeftMost(); expect(leftMost?.key).toBe(1); @@ -582,27 +578,26 @@ describe('BST operations test recursively', () => { it('should perform various operations on a Binary Search Tree with object values', () => { const objBST = new BST<{ key: number; keyA: number }>(); expect(objBST).toBeInstanceOf(BST); - objBST.add(11, { key: 11, keyA: 11 }); - objBST.add(3, { key: 3, keyA: 3 }); - const values = [ - { key: 15, keyA: 15 }, - { key: 1, keyA: 1 }, - { key: 8, keyA: 8 }, - { key: 13, keyA: 13 }, - { key: 16, keyA: 16 }, - { key: 2, keyA: 2 }, - { key: 6, keyA: 6 }, - { key: 9, keyA: 9 }, - { key: 12, keyA: 12 }, - { key: 14, keyA: 14 }, - { key: 4, keyA: 4 }, - { key: 7, keyA: 7 }, - { key: 10, keyA: 10 }, - { key: 5, keyA: 5 } + objBST.add([11, { key: 11, keyA: 11 }]); + objBST.add([3, { key: 3, keyA: 3 }]); + const values: [number, { key: number; keyA: number }][] = [ + [15, { key: 15, keyA: 15 }], + [1, { key: 1, keyA: 1 }], + [8, { key: 8, keyA: 8 }], + [13, { key: 13, keyA: 13 }], + [16, { key: 16, keyA: 16 }], + [2, { key: 2, keyA: 2 }], + [6, { key: 6, keyA: 6 }], + [9, { key: 9, keyA: 9 }], + [12, { key: 12, keyA: 12 }], + [14, { key: 14, keyA: 14 }], + [4, { key: 4, keyA: 4 }], + [7, { key: 7, keyA: 7 }], + [10, { key: 10, keyA: 10 }], + [5, { key: 5, keyA: 5 }] ]; objBST.addMany( - values.map(item => item.key), values, false ); @@ -834,7 +829,7 @@ describe('BST Performance test', function () { it('should the lastKey of a BST to be the largest key', function () { const bst = new BST(); - bst.addMany([9, 8, 7, 3, 1, 2, 5, 4, 6], undefined, false); + bst.addMany([9, 8, 7, 3, 1, 2, 5, 4, 6], false); expect(bst.lastKey()).toBe(9); }); @@ -856,9 +851,9 @@ describe('BST iterative methods test', () => { let bst: BST; beforeEach(() => { bst = new BST(); - bst.add(1, 'a'); - bst.add(2, 'b'); - bst.add(3, 'c'); + bst.add([1, 'a']); + bst.add([2, 'b']); + bst.add([3, 'c']); }); test('The node obtained by get Node should match the node type', () => { diff --git a/test/unit/data-structures/binary-tree/overall.test.ts b/test/unit/data-structures/binary-tree/overall.test.ts index d4f316a..58517ab 100644 --- a/test/unit/data-structures/binary-tree/overall.test.ts +++ b/test/unit/data-structures/binary-tree/overall.test.ts @@ -5,7 +5,7 @@ describe('Overall BinaryTree Test', () => { const bst = new BST(); bst.add(11); bst.add(3); - bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], undefined, false); + bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], false); bst.size === 16; // true expect(bst.size).toBe(16); // true bst.has(6); // true @@ -30,26 +30,25 @@ describe('Overall BinaryTree Test', () => { expect(bfsIDs[0]).toBe(11); const objBST = new BST<{ key: number; keyA: number }>(); - objBST.add(11, { key: 11, keyA: 11 }); - objBST.add(3, { key: 3, keyA: 3 }); + objBST.add([11, { key: 11, keyA: 11 }]); + objBST.add([3, { key: 3, keyA: 3 }]); objBST.addMany( - [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], [ - { key: 15, keyA: 15 }, - { key: 1, keyA: 1 }, - { key: 8, keyA: 8 }, - { key: 13, keyA: 13 }, - { key: 16, keyA: 16 }, - { key: 2, keyA: 2 }, - { key: 6, keyA: 6 }, - { key: 9, keyA: 9 }, - { key: 12, keyA: 12 }, - { key: 14, keyA: 14 }, - { key: 4, keyA: 4 }, - { key: 7, keyA: 7 }, - { key: 10, keyA: 10 }, - { key: 5, keyA: 5 } + [15, { key: 15, keyA: 15 }], + [1, { key: 1, keyA: 1 }], + [8, { key: 8, keyA: 8 }], + [13, { key: 13, keyA: 13 }], + [16, { key: 16, keyA: 16 }], + [2, { key: 2, keyA: 2 }], + [6, { key: 6, keyA: 6 }], + [9, { key: 9, keyA: 9 }], + [12, { key: 12, keyA: 12 }], + [14, { key: 14, keyA: 14 }], + [4, { key: 4, keyA: 4 }], + [7, { key: 7, keyA: 7 }], + [10, { key: 10, keyA: 10 }], + [5, { key: 5, keyA: 5 }] ] ); 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 26c129f..3c675c7 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -510,9 +510,9 @@ describe('RedBlackTree iterative methods test', () => { let rbTree: RedBlackTree; beforeEach(() => { rbTree = new RedBlackTree(); - rbTree.add(1, 'a'); - rbTree.add(2, 'b'); - rbTree.add(3, 'c'); + rbTree.add([1, 'a']); + rbTree.add([2, 'b']); + rbTree.add([3, 'c']); }); test('The node obtained by get Node should match the node type', () => { diff --git a/test/unit/data-structures/binary-tree/tree-multimap.test.ts b/test/unit/data-structures/binary-tree/tree-multimap.test.ts index ceb71ce..56d50ed 100644 --- a/test/unit/data-structures/binary-tree/tree-multimap.test.ts +++ b/test/unit/data-structures/binary-tree/tree-multimap.test.ts @@ -3,6 +3,16 @@ import { isDebugTest } from '../../../config'; const isDebug = isDebugTest; +describe('TreeMultimap count', () => { + const tm = new TreeMultimap(); + + it('Should count', () => { + tm.addMany([[1, 1], [2, 2], [3, 3]]); + tm.lesserOrGreaterTraverse(node => node.count += 2, CP.gt, 1); + expect(tm.count).toBe(7) + }) +}) + describe('TreeMultimap operations test', () => { it('should perform various operations on a Binary Search Tree with numeric values', () => { const treeMultimap = new TreeMultimap(); @@ -10,8 +20,25 @@ describe('TreeMultimap operations test', () => { expect(treeMultimap instanceof TreeMultimap); treeMultimap.add(11, 11); treeMultimap.add(3, 3); - const idAndValues = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; - treeMultimap.addMany(idAndValues, idAndValues); + const idAndValues: [number, number][] = [ + [11, 11], + [3, 3], + [15, 15], + [1, 1], + [8, 8], + [13, 13], + [16, 16], + [2, 2], + [6, 6], + [9, 9], + [12, 12], + [14, 14], + [4, 4], + [7, 7], + [10, 10], + [5, 5] + ]; + treeMultimap.addMany(idAndValues); expect(treeMultimap.root instanceof TreeMultimapNode); if (treeMultimap.root) expect(treeMultimap.root.key == 11); @@ -209,27 +236,26 @@ describe('TreeMultimap operations test', () => { it('should perform various operations on a Binary Search Tree with object values', () => { const objTreeMultimap = new TreeMultimap<{ key: number; keyA: number }>(); expect(objTreeMultimap).toBeInstanceOf(TreeMultimap); - objTreeMultimap.add(11, { key: 11, keyA: 11 }); - objTreeMultimap.add(3, { key: 3, keyA: 3 }); - const values = [ - { key: 15, keyA: 15 }, - { key: 1, keyA: 1 }, - { key: 8, keyA: 8 }, - { key: 13, keyA: 13 }, - { key: 16, keyA: 16 }, - { key: 2, keyA: 2 }, - { key: 6, keyA: 6 }, - { key: 9, keyA: 9 }, - { key: 12, keyA: 12 }, - { key: 14, keyA: 14 }, - { key: 4, keyA: 4 }, - { key: 7, keyA: 7 }, - { key: 10, keyA: 10 }, - { key: 5, keyA: 5 } + objTreeMultimap.add([11, { key: 11, keyA: 11 }]); + objTreeMultimap.add([3, { key: 3, keyA: 3 }]); + const values: [number, { key: number, keyA: number }][] = [ + [15, { key: 15, keyA: 15 }], + [1, { key: 1, keyA: 1 }], + [8, { key: 8, keyA: 8 }], + [13, { key: 13, keyA: 13 }], + [16, { key: 16, keyA: 16 }], + [2, { key: 2, keyA: 2 }], + [6, { key: 6, keyA: 6 }], + [9, { key: 9, keyA: 9 }], + [12, { key: 12, keyA: 12 }], + [14, { key: 14, keyA: 14 }], + [4, { key: 4, keyA: 4 }], + [7, { key: 7, keyA: 7 }], + [10, { key: 10, keyA: 10 }], + [5, { key: 5, keyA: 5 }] ]; objTreeMultimap.addMany( - values.map(item => item.key), values ); @@ -245,14 +271,31 @@ describe('TreeMultimap operations test', () => { describe('TreeMultimap operations test recursively', () => { it('should perform various operations on a Binary Search Tree with numeric values', () => { - const treeMultimap = new TreeMultimap([], { iterationType: IterationType.RECURSIVE }); + const treeMultimap = new TreeMultimap([], { iterationType: IterationType.RECURSIVE }); expect(treeMultimap instanceof TreeMultimap); treeMultimap.add(11, 11); treeMultimap.add(3, 3); - const idAndValues = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; - treeMultimap.addMany(idAndValues, idAndValues); - expect(treeMultimap.root instanceof TreeMultimapNode); + const idAndValues: [number, number][] = [ + [11, 11], + [3, 3], + [15, 15], + [1, 1], + [8, 8], + [13, 13], + [16, 16], + [2, 2], + [6, 6], + [9, 9], + [12, 12], + [14, 14], + [4, 4], + [7, 7], + [10, 10], + [5, 5] + ]; + treeMultimap.addMany(idAndValues); + expect(treeMultimap.root).toBeInstanceOf(TreeMultimapNode); if (treeMultimap.root) expect(treeMultimap.root.key == 11); @@ -449,27 +492,26 @@ describe('TreeMultimap operations test recursively', () => { it('should perform various operations on a Binary Search Tree with object values', () => { const objTreeMultimap = new TreeMultimap<{ key: number; keyA: number }>(); expect(objTreeMultimap).toBeInstanceOf(TreeMultimap); - objTreeMultimap.add(11, { key: 11, keyA: 11 }); - objTreeMultimap.add(3, { key: 3, keyA: 3 }); - const values = [ - { key: 15, keyA: 15 }, - { key: 1, keyA: 1 }, - { key: 8, keyA: 8 }, - { key: 13, keyA: 13 }, - { key: 16, keyA: 16 }, - { key: 2, keyA: 2 }, - { key: 6, keyA: 6 }, - { key: 9, keyA: 9 }, - { key: 12, keyA: 12 }, - { key: 14, keyA: 14 }, - { key: 4, keyA: 4 }, - { key: 7, keyA: 7 }, - { key: 10, keyA: 10 }, - { key: 5, keyA: 5 } + objTreeMultimap.add([11, { key: 11, keyA: 11 }]); + objTreeMultimap.add([3, { key: 3, keyA: 3 }]); + const values: [number, { key: number; keyA: number }][] = [ + [15, { key: 15, keyA: 15 }], + [1, { key: 1, keyA: 1 }], + [8, { key: 8, keyA: 8 }], + [13, { key: 13, keyA: 13 }], + [16, { key: 16, keyA: 16 }], + [2, { key: 2, keyA: 2 }], + [6, { key: 6, keyA: 6 }], + [9, { key: 9, keyA: 9 }], + [12, { key: 12, keyA: 12 }], + [14, { key: 14, keyA: 14 }], + [4, { key: 4, keyA: 4 }], + [7, { key: 7, keyA: 7 }], + [10, { key: 10, keyA: 10 }], + [5, { key: 5, keyA: 5 }] ]; objTreeMultimap.addMany( - values.map(item => item.key), values );