From d6b394446a4f3cbf729063171c8fd5dc74dfd254 Mon Sep 17 00:00:00 2001 From: Revone Date: Sun, 5 Nov 2023 21:19:59 +0800 Subject: [PATCH] [binary-tree] All traversal methods offer an includeNull parameter to support the output of null nodes. --- CHANGELOG.md | 2 +- README.md | 24 +- .../binary-tree/binary-tree.ts | 266 ++++++++++++++---- .../binary-tree/binary-tree.test.ts | 33 ++- 4 files changed, 249 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c4d84..798f63e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - [Semantic Versioning](https://semver.org/spec/v2.0.0.html) - [`auto-changelog`](https://github.com/CookPete/auto-changelog) -## [v1.41.8](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.41.9](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/README.md b/README.md index 1efbc38..1af0d62 100644 --- a/README.md +++ b/README.md @@ -658,40 +658,40 @@ optimal approach to data structure design. [//]: # (Start of Replace Section)
avl-tree
-
test nametime taken (ms)executions per secsample deviation
10,000 add randomly30.2933.013.64e-4
10,000 add & delete randomly68.1014.680.00
10,000 addMany39.5425.294.07e-4
10,000 get26.7237.423.77e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 add randomly30.1833.132.75e-4
10,000 add & delete randomly65.6515.230.00
10,000 addMany39.5625.283.25e-4
10,000 get26.5737.631.92e-4
binary-tree
-
test nametime taken (ms)executions per secsample deviation
1,000 add randomly12.8877.631.02e-4
1,000 add & delete randomly15.9062.881.08e-4
1,000 addMany10.5994.418.39e-5
1,000 get18.0155.531.95e-4
1,000 dfs69.1114.476.47e-4
1,000 bfs54.4218.384.20e-4
1,000 morris37.1426.922.27e-4
+
test nametime taken (ms)executions per secsample deviation
1,000 add randomly13.0076.933.84e-4
1,000 add & delete randomly16.1162.063.76e-4
1,000 addMany10.6394.041.30e-4
1,000 get18.2454.845.04e-4
1,000 dfs69.7714.334.07e-4
1,000 bfs54.4918.354.96e-4
1,000 morris37.1026.962.35e-4
bst
-
test nametime taken (ms)executions per secsample deviation
10,000 add randomly28.4835.112.29e-4
10,000 add & delete randomly64.8215.430.01
10,000 addMany28.7434.809.06e-4
10,000 get27.3836.521.82e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 add randomly31.8831.373.10e-4
10,000 add & delete randomly73.0813.680.01
10,000 addMany28.8034.730.00
10,000 get27.5936.252.19e-4
rb-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add randomly72.3013.830.00
100,000 add & 1000 delete randomly81.3712.290.01
100,000 getNode59.4816.819.29e-4
+
test nametime taken (ms)executions per secsample deviation
100,000 add randomly70.9714.090.00
100,000 add & 1000 delete randomly82.0312.190.01
100,000 getNode59.7516.740.00
directed-graph
-
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109786.775.56e-7
1,000 addEdge6.02166.041.27e-4
1,000 getVertex0.052.18e+43.02e-7
1,000 getEdge23.4142.710.00
tarjan223.514.470.01
tarjan all224.894.450.00
topologicalSort181.905.500.00
+
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109894.621.57e-6
1,000 addEdge6.17162.150.00
1,000 getVertex0.052.17e+44.06e-7
1,000 getEdge23.5042.560.00
tarjan223.184.480.01
tarjan all226.104.420.01
topologicalSort186.205.370.02
heap
-
test nametime taken (ms)executions per secsample deviation
10,000 add & pop4.62216.333.06e-5
10,000 fib add & pop351.412.850.00
+
test nametime taken (ms)executions per secsample deviation
10,000 add & pop4.64215.304.51e-5
10,000 fib add & pop351.832.840.00
doubly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 unshift214.844.650.04
1,000,000 unshift & shift167.115.980.04
1,000,000 insertBefore335.782.980.07
+
test nametime taken (ms)executions per secsample deviation
1,000,000 unshift216.194.630.04
1,000,000 unshift & shift164.846.070.02
1,000,000 insertBefore325.143.080.07
singly-linked-list
-
test nametime taken (ms)executions per secsample deviation
10,000 push & pop212.534.710.01
10,000 insertBefore243.944.100.00
+
test nametime taken (ms)executions per secsample deviation
10,000 push & pop213.244.690.01
10,000 insertBefore247.694.040.01
max-priority-queue
-
test nametime taken (ms)executions per secsample deviation
10,000 refill & poll11.4387.501.84e-4
+
test nametime taken (ms)executions per secsample deviation
10,000 refill & poll11.5086.971.99e-4
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push216.074.630.05
1,000,000 shift24.9740.050.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push223.304.480.08
1,000,000 shift24.8640.230.00
queue
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push42.5723.490.01
1,000,000 push & shift79.9412.519.99e-4
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push42.2623.660.01
1,000,000 push & shift79.2212.620.00
trie
-
test nametime taken (ms)executions per secsample deviation
100,000 push54.0218.510.00
100,000 getWords82.8312.070.00
+
test nametime taken (ms)executions per secsample deviation
100,000 push52.9218.900.00
100,000 getWords83.3711.990.00
[//]: # (End of Replace Section) \ No newline at end of file diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 6a9378d..68416a1 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -108,8 +108,7 @@ export class BinaryTreeNode = BinaryTree * @template N - The type of the binary tree's nodes. */ export class BinaryTree = BinaryTreeNode>> - implements IBinaryTree -{ + implements IBinaryTree { iterationType: IterationType = IterationType.ITERATIVE; /** @@ -391,7 +390,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) { @@ -846,6 +845,27 @@ export class BinaryTree = BinaryTreeNode return this.isSubtreeBST(this.root, iterationType); } + subTreeTraverse>( + callback?: C, + beginRoot?: BTNKey | N | null, + iterationType?: IterationType, + includeNull?: false + ): ReturnType[] + + subTreeTraverse>( + callback?: C, + beginRoot?: BTNKey | N | null, + iterationType?: IterationType, + includeNull?: undefined + ): ReturnType[] + + subTreeTraverse>( + callback?: C, + beginRoot?: BTNKey | N | null, + iterationType?: IterationType, + includeNull?: true + ): ReturnType[] + /** * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each * node, either recursively or iteratively. @@ -858,40 +878,79 @@ export class BinaryTree = BinaryTreeNode * start from the root of the tree. * @param iterationType - The `iterationType` parameter determines the type of traversal to be * performed on the binary tree. It can have two possible values: + * @param includeNull - The choice to output null values during binary tree traversal should be provided. * @returns The function `subTreeTraverse` returns an array of `ReturnType>`. */ - subTreeTraverse>( + subTreeTraverse>( callback: C = this.defaultOneParamCallback as C, beginRoot: BTNKey | N | null = this.root, - iterationType = this.iterationType + iterationType = this.iterationType, + includeNull = false ): ReturnType[] { if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot); - const ans: ReturnType>[] = []; + const ans: (ReturnType> | null)[] = []; if (!beginRoot) return ans; if (iterationType === IterationType.RECURSIVE) { - const _traverse = (cur: N) => { - ans.push(callback(cur)); - cur.left && _traverse(cur.left); - cur.right && _traverse(cur.right); + const _traverse = (cur: N | null) => { + if (cur !== undefined) { + ans.push(callback(cur)); + if (includeNull) { + cur !== null && cur.left !== undefined && _traverse(cur.left); + cur !== null && cur.right !== undefined && _traverse(cur.right); + } else { + cur !== null && cur.left && _traverse(cur.left); + cur !== null && cur.right && _traverse(cur.right); + } + } }; _traverse(beginRoot); } else { - const stack: N[] = [beginRoot]; + const stack: (N| null)[] = [beginRoot]; while (stack.length > 0) { - const cur = stack.pop()!; - - ans.push(callback(cur)); - cur.right && stack.push(cur.right); - cur.left && stack.push(cur.left); + const cur = stack.pop(); + if (cur !== undefined) { + ans.push(callback(cur)); + if (includeNull) { + cur !== null && cur.right !== undefined && stack.push(cur.right); + cur !== null && cur.left !== undefined && stack.push(cur.left); + } else { + cur !== null && cur.right && stack.push(cur.right); + cur !== null && cur.left && stack.push(cur.left); + } + } } } return ans; } + dfs>( + callback?: C, + pattern?: DFSOrderPattern, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: false + ): ReturnType[] + + dfs>( + callback?: C, + pattern?: DFSOrderPattern, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: undefined + ): ReturnType[] + + dfs>( + callback?: C, + pattern?: DFSOrderPattern, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: true + ): ReturnType[] + /** * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback * function on each node according to a specified order pattern. @@ -905,34 +964,53 @@ export class BinaryTree = BinaryTreeNode * is `null`, an empty array will be returned. * @param {IterationType} iterationType - The `iterationType` parameter determines the type of * iteration used in the depth-first search algorithm. It can have two possible values: + * @param includeNull - The choice to output null values during binary tree traversal should be provided. * @returns The function `dfs` returns an array of `ReturnType>` values. */ - dfs>( + dfs>( callback: C = this.defaultOneParamCallback as C, pattern: DFSOrderPattern = 'in', beginRoot: N | null = this.root, - iterationType: IterationType = IterationType.ITERATIVE + iterationType: IterationType = IterationType.ITERATIVE, + includeNull = false ): ReturnType[] { if (!beginRoot) return []; - const ans: ReturnType>[] = []; + const ans: ReturnType[] = []; if (iterationType === IterationType.RECURSIVE) { - const _traverse = (node: N) => { + const _traverse = (node: N | null) => { switch (pattern) { case 'in': - if (node.left) _traverse(node.left); - ans.push(callback(node)); - if (node.right) _traverse(node.right); + if (includeNull) { + if (node !== null && node.left !== undefined) _traverse(node.left); + ans.push(callback(node)); + if (node !== null && node.right !== undefined) _traverse(node.right); + } else { + if (node !== null && node.left) _traverse(node.left); + ans.push(callback(node)); + if (node !== null && node.right) _traverse(node.right); + } break; case 'pre': - ans.push(callback(node)); - - if (node.left) _traverse(node.left); - if (node.right) _traverse(node.right); + if (includeNull) { + ans.push(callback(node)); + if (node !== null && node.left !== undefined) _traverse(node.left); + if (node !== null && node.right !== undefined) _traverse(node.right); + } else { + ans.push(callback(node)); + if (node !== null && node.left) _traverse(node.left); + if (node !== null && node.right) _traverse(node.right); + } break; case 'post': - if (node.left) _traverse(node.left); - if (node.right) _traverse(node.right); - ans.push(callback(node)); + if (includeNull) { + if (node !== null && node.left !== undefined) _traverse(node.left); + if (node !== null && node.right !== undefined) _traverse(node.right); + ans.push(callback(node)); + } else { + if (node !== null && node.left) _traverse(node.left); + if (node !== null && node.right) _traverse(node.right); + ans.push(callback(node)); + } break; } @@ -941,34 +1019,39 @@ 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(); - if (!cur || !cur.node) continue; + if (cur === undefined) continue; + if (includeNull) { + if (cur.node === undefined) continue; + } else { + if (cur.node === null || cur.node === undefined) continue; + } if (cur.opt === 1) { ans.push(callback(cur.node)); } else { switch (pattern) { case 'in': - stack.push({opt: 0, node: cur.node.right}); + cur.node && stack.push({opt: 0, node: cur.node.right}); stack.push({opt: 1, node: cur.node}); - stack.push({opt: 0, node: cur.node.left}); + cur.node && stack.push({opt: 0, node: cur.node.left}); break; case 'pre': - stack.push({opt: 0, node: cur.node.right}); - stack.push({opt: 0, node: cur.node.left}); + cur.node && stack.push({opt: 0, node: cur.node.right}); + cur.node && stack.push({opt: 0, node: cur.node.left}); stack.push({opt: 1, node: cur.node}); break; case 'post': stack.push({opt: 1, node: cur.node}); - stack.push({opt: 0, node: cur.node.right}); - stack.push({opt: 0, node: cur.node.left}); + cur.node && stack.push({opt: 0, node: cur.node.right}); + cur.node && stack.push({opt: 0, node: cur.node.left}); break; default: - stack.push({opt: 0, node: cur.node.right}); + cur.node && stack.push({opt: 0, node: cur.node.right}); stack.push({opt: 1, node: cur.node}); - stack.push({opt: 0, node: cur.node.left}); + cur.node && stack.push({opt: 0, node: cur.node.left}); break; } } @@ -978,6 +1061,27 @@ export class BinaryTree = BinaryTreeNode return ans; } + bfs>( + callback?: C, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: false + ): ReturnType[] + + bfs>( + callback?: C, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: undefined + ): ReturnType[] + + bfs>( + callback?: C, + beginRoot?: N | null, + iterationType?: IterationType, + includeNull?: true + ): ReturnType[] + /** * The bfs function performs a breadth-first search traversal on a binary tree, executing a callback * function on each node. @@ -989,19 +1093,21 @@ export class BinaryTree = BinaryTreeNode * will not be performed and an empty array will be returned. * @param iterationType - The `iterationType` parameter determines the type of iteration to be used * in the breadth-first search (BFS) algorithm. It can have two possible values: + * @param includeNull - The choice to output null values during binary tree traversal should be provided. * @returns The function `bfs` returns an array of `ReturnType>[]`. */ - bfs>( + bfs>( callback: C = this.defaultOneParamCallback as C, beginRoot: N | null = this.root, - iterationType = this.iterationType + iterationType = this.iterationType, + includeNull = false ): ReturnType[] { if (!beginRoot) return []; const ans: ReturnType>[] = []; if (iterationType === IterationType.RECURSIVE) { - const queue = new Queue([beginRoot]); + const queue: Queue = new Queue([beginRoot]); const traverse = (level: number) => { if (queue.size === 0) return; @@ -1009,15 +1115,21 @@ export class BinaryTree = BinaryTreeNode const current = queue.shift()!; ans.push(callback(current)); - if (current.left) queue.push(current.left); - if (current.right) queue.push(current.right); + if (includeNull) { + if (current && current.left !== undefined) queue.push(current.left); + if (current && current.right !== undefined) queue.push(current.right); + } else { + if (current.left) queue.push(current.left); + if (current.right) queue.push(current.right); + } + traverse(level + 1); }; traverse(0); } else { - const queue = new Queue([beginRoot]); + const queue = new Queue([beginRoot]); while (queue.size > 0) { const levelSize = queue.size; @@ -1025,14 +1137,41 @@ export class BinaryTree = BinaryTreeNode const current = queue.shift()!; ans.push(callback(current)); - if (current.left) queue.push(current.left); - if (current.right) queue.push(current.right); + if (includeNull) { + if (current !== null && current.left !== undefined) queue.push(current.left); + if (current !== null && current.right !== undefined) queue.push(current.right); + } else { + if (current.left) queue.push(current.left); + if (current.right) queue.push(current.right); + } + } } } return ans; } + listLevels>( + callback?: C , + beginRoot?: N | null , + iterationType?: IterationType, + includeNull?: false + ): ReturnType[][] + + listLevels>( + callback?: C , + beginRoot?: N | null , + iterationType?: IterationType, + includeNull?: undefined + ): ReturnType[][] + + listLevels>( + callback?: C , + beginRoot?: N | null , + iterationType?: IterationType, + includeNull?: true + ): ReturnType[][] + /** * The `listLevels` function takes a binary tree node and a callback function, and returns an array * of arrays representing the levels of the tree. @@ -1044,29 +1183,36 @@ export class BinaryTree = BinaryTreeNode * from the root node of the binary tree. * @param iterationType - The `iterationType` parameter determines whether the tree traversal is done * recursively or iteratively. It can have two possible values: + * @param includeNull - The choice to output null values during binary tree traversal should be provided. * @returns The function `listLevels` returns an array of arrays, where each inner array represents a * level in a binary tree. Each inner array contains the return type of the provided callback * function `C` applied to the nodes at that level. */ - listLevels>( + listLevels>( callback: C = this.defaultOneParamCallback as C, beginRoot: N | null = this.root, - iterationType = this.iterationType + iterationType = this.iterationType, + includeNull = false ): ReturnType[][] { if (!beginRoot) return []; const levelsNodes: ReturnType[][] = []; if (iterationType === IterationType.RECURSIVE) { - const _recursive = (node: N, level: number) => { + const _recursive = (node: N | null, level: number) => { if (!levelsNodes[level]) levelsNodes[level] = []; levelsNodes[level].push(callback(node)); - if (node.left) _recursive(node.left, level + 1); - if (node.right) _recursive(node.right, level + 1); + if (includeNull) { + if (node && node.left !== undefined) _recursive(node.left, level + 1); + if (node && node.right !== undefined) _recursive(node.right, level + 1); + } else { + if (node && node.left) _recursive(node.left, level + 1); + if (node && node.right) _recursive(node.right, level + 1); + } }; _recursive(beginRoot, 0); } else { - const stack: [N, number][] = [[beginRoot, 0]]; + const stack: [N | null, number][] = [[beginRoot, 0]]; while (stack.length > 0) { const head = stack.pop()!; @@ -1074,8 +1220,14 @@ export class BinaryTree = BinaryTreeNode if (!levelsNodes[level]) levelsNodes[level] = []; levelsNodes[level].push(callback(node)); - if (node.right) stack.push([node.right, level + 1]); - if (node.left) stack.push([node.left, level + 1]); + + if (includeNull) { + if (node && node.right !== undefined) stack.push([node.right, level + 1]); + if (node && node.left !== undefined) stack.push([node.left, level + 1]); + } else { + if (node && node.right) stack.push([node.right, level + 1]); + if (node && node.left) stack.push([node.left, level + 1]); + } } } @@ -1231,7 +1383,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/test/unit/data-structures/binary-tree/binary-tree.test.ts b/test/unit/data-structures/binary-tree/binary-tree.test.ts index 5970b72..e70a3f8 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -174,8 +174,11 @@ describe('BinaryTree', () => { }); it('should subTreeTraverse', () => { - tree.addMany([4, 2, 6, 1, 3, 5, 7]); - expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]); + tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]); + expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.ITERATIVE)).toEqual([6,3, 7]); + expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6,3, 7]); + expect(tree.subTreeTraverse(node => node === null? null : node.key, tree.getNode(6), IterationType.ITERATIVE, true)).toEqual([6, 3, 7, null]); + expect(tree.subTreeTraverse(node => node === null? null : node.key, tree.getNode(6), IterationType.RECURSIVE, true)).toEqual([6, 3, 7, null]); }); it('should clear the tree', () => { @@ -266,10 +269,18 @@ describe('BinaryTree traversals', () => { const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]; tree.refill(arr); + expect(tree.bfs(node => node , tree.root, IterationType.ITERATIVE, true).map(node => node === null ? null : node.key)).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]); + expect(tree.bfs(node => node , tree.root, IterationType.RECURSIVE, true).map(node => node === null ? null : node.key)).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]); + expect(tree.bfs(node => node , tree.root, IterationType.ITERATIVE).map(node => node === null ? null : node.key)).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]); + expect(tree.bfs(node => node , tree.root, IterationType.RECURSIVE).map(node => node === null ? null : node.key)).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]); + expect(tree.dfs(node => node.key, 'pre')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]); expect(tree.dfs(node => node.key, 'pre', tree.root, IterationType.RECURSIVE)).toEqual([ 35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55 ]); + expect(tree.dfs(node => node, 'pre', tree.root, IterationType.ITERATIVE, true).map(node => node === null ? null : node.key)).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]); + expect(tree.dfs(node => node, 'pre', tree.root, IterationType.RECURSIVE, true).map(node => node === null ? null : node.key)).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]); + expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]); expect(tree.dfs(node => node.key, 'post')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]); expect(tree.dfs(node => node.key, 'post', tree.root, IterationType.RECURSIVE)).toEqual([ @@ -282,9 +293,7 @@ describe('BinaryTree traversals', () => { 35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55 ]); - const levels = tree.listLevels(node => node.key); - expect(levels).toEqual([[35], [20, 40], [15, 29, 50], [16, 28, 30, 45, 55]]); - isDebug && console.log(levels); + expect(tree.listLevels(node => node.key)).toEqual([[35], [20, 40], [15, 29, 50], [16, 28, 30, 45, 55]]); expect(tree.listLevels(node => node.key, tree.root, IterationType.RECURSIVE)).toEqual([ [35], @@ -292,9 +301,21 @@ describe('BinaryTree traversals', () => { [15, 29, 50], [16, 28, 30, 45, 55] ]); - isDebug && console.log(levels); + expect(tree.listLevels(node => node === null ? null :node.key, tree.root, IterationType.ITERATIVE, true)).toEqual([ + [35], + [20, 40], + [15, 29, null,50], + [null, 16, 28, 30, 45, 55] + ]); + expect(tree.listLevels(node => node === null ? null :node.key, tree.root, IterationType.RECURSIVE, true)).toEqual([ + [35], + [20, 40], + [15, 29, null,50], + [null, 16, 28, 30, 45, 55] + ]); }); + describe('BinaryTree', () => { let tree: BinaryTree;