From e271f73de0411b6264c2fa6efe75b15ca6f49dde Mon Sep 17 00:00:00 2001 From: Revone Date: Mon, 21 Oct 2024 19:14:36 +1300 Subject: [PATCH] feat: Refactor the BinaryTree's dfs method into a private helper function _dfs to prepare for a more generic implementation. --- README.md | 26 +- .../binary-tree/binary-tree.ts | 248 ++++++++++++------ src/data-structures/binary-tree/bst.ts | 2 +- .../binary-tree/binary-tree.ts | 9 +- .../binary-tree/binary-tree.test.ts | 165 +++++++++++- 5 files changed, 340 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 3d44a8f..a600003 100644 --- a/README.md +++ b/README.md @@ -823,43 +823,43 @@ Version 11.7.9 [//]: # (No deletion!!! Start of Replace Section)
heap
-
test nametime taken (ms)executions per secsample deviation
100,000 add8.07123.930.00
100,000 add & poll45.3222.070.01
+
test nametime taken (ms)executions per secsample deviation
100,000 add7.60131.642.41e-4
100,000 add & poll44.0422.710.00
rb-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add77.0312.980.00
100,000 add randomly83.2612.010.00
100,000 get120.258.320.01
100,000 iterator26.3237.990.01
100,000 add & delete orderly161.686.190.01
100,000 add & delete randomly268.633.720.03
+
test nametime taken (ms)executions per secsample deviation
100,000 add77.1112.970.00
100,000 add randomly81.3812.290.00
100,000 get112.228.910.00
100,000 iterator28.6434.910.00
100,000 add & delete orderly158.806.300.02
100,000 add & delete randomly230.074.350.00
queue
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push45.5521.960.02
100,000 push & shift5.54180.360.00
Native JS Array 100,000 push & shift2467.710.410.20
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push42.2623.670.01
100,000 push & shift5.07197.325.97e-4
Native JS Array 100,000 push & shift2252.790.440.17
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push25.3639.430.00
1,000,000 push & pop32.1331.120.00
1,000,000 push & shift33.4229.920.00
100,000 push & shift3.59278.923.21e-4
Native JS Array 100,000 push & shift2427.030.410.21
100,000 unshift & shift3.56280.813.81e-4
Native JS Array 100,000 unshift & shift4464.180.220.07
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push23.3042.920.00
1,000,000 push & pop31.9031.340.00
1,000,000 push & shift32.7030.580.00
100,000 push & shift3.40293.732.64e-4
Native JS Array 100,000 push & shift2225.020.450.08
100,000 unshift & shift3.34299.682.48e-4
Native JS Array 100,000 unshift & shift3993.220.250.13
hash-map
-
test nametime taken (ms)executions per secsample deviation
1,000,000 set313.053.190.07
Native JS Map 1,000,000 set224.484.450.05
Native JS Set 1,000,000 add203.464.910.05
1,000,000 set & get281.793.550.07
Native JS Map 1,000,000 set & get289.573.450.03
Native JS Set 1,000,000 add & has195.735.110.02
1,000,000 ObjKey set & get348.392.870.03
Native JS Map 1,000,000 ObjKey set & get315.233.170.04
Native JS Set 1,000,000 ObjKey add & has335.832.980.06
+
test nametime taken (ms)executions per secsample deviation
1,000,000 set106.429.400.01
Native JS Map 1,000,000 set204.684.890.01
Native JS Set 1,000,000 add166.126.020.01
1,000,000 set & get118.988.400.02
Native JS Map 1,000,000 set & get265.163.770.01
Native JS Set 1,000,000 add & has169.185.910.01
1,000,000 ObjKey set & get315.903.170.03
Native JS Map 1,000,000 ObjKey set & get291.113.440.03
Native JS Set 1,000,000 ObjKey add & has272.993.660.04
trie
-
test nametime taken (ms)executions per secsample deviation
100,000 push48.0920.790.00
100,000 getWords93.1710.730.01
+
test nametime taken (ms)executions per secsample deviation
100,000 push44.8122.310.00
100,000 getWords83.7511.940.00
avl-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add278.913.590.01
100,000 add randomly350.652.850.02
100,000 get154.976.450.03
100,000 iterator34.7828.750.02
100,000 add & delete orderly445.452.240.00
100,000 add & delete randomly616.611.620.03
+
test nametime taken (ms)executions per secsample deviation
100,000 add270.913.690.02
100,000 add randomly344.712.900.00
100,000 get128.807.760.00
100,000 iterator32.8830.410.01
100,000 add & delete orderly456.462.190.00
100,000 add & delete randomly604.251.650.00
binary-tree-overall
-
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add randomly7.07141.457.19e-4
10,000 RBTree get randomly9.33107.211.48e-4
10,000 RBTree add & delete randomly18.6053.773.93e-4
10,000 AVLTree add randomly30.3932.910.01
10,000 AVLTree get randomly10.7093.490.00
10,000 AVLTree add & delete randomly46.0421.720.00
+
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add randomly6.64150.668.06e-5
10,000 RBTree get randomly9.24108.231.40e-4
10,000 RBTree add & delete randomly18.2554.792.59e-4
10,000 AVLTree add randomly23.5742.431.78e-4
10,000 AVLTree get randomly9.69103.218.94e-5
10,000 AVLTree add & delete randomly44.3722.544.23e-4
directed-graph
-
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.137502.536.69e-5
1,000 addEdge7.93126.130.00
1,000 getVertex0.052.19e+41.17e-5
1,000 getEdge18.6553.610.00
tarjan158.866.300.01
topologicalSort141.917.050.01
+
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109718.491.33e-6
1,000 addEdge6.28159.341.59e-4
1,000 getVertex0.042.57e+45.33e-7
1,000 getEdge22.4344.580.00
tarjan200.864.980.01
topologicalSort176.955.650.01
doubly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push211.264.730.03
1,000,000 unshift216.904.610.07
1,000,000 unshift & shift208.454.800.05
1,000,000 addBefore316.553.160.06
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push205.864.860.07
1,000,000 unshift199.965.000.03
1,000,000 unshift & shift180.945.530.02
1,000,000 addBefore308.983.240.10
singly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift222.814.490.08
10,000 push & pop235.914.240.01
10,000 addBefore250.573.990.01
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift206.484.840.09
10,000 push & pop224.134.460.01
10,000 addBefore246.924.050.00
priority-queue
-
test nametime taken (ms)executions per secsample deviation
100,000 add27.6436.178.81e-4
100,000 add & poll75.5213.249.91e-4
+
test nametime taken (ms)executions per secsample deviation
100,000 add27.0237.012.69e-4
100,000 add & poll75.9713.165.61e-4
stack
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push40.4724.710.01
1,000,000 push & pop47.4721.070.01
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push38.5225.960.00
1,000,000 push & pop46.9521.300.01
[//]: # (No deletion!!! End of Replace Section) diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 358bd9d..bb08900 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -27,6 +27,7 @@ import { trampoline } from '../../utils'; import { Queue } from '../queue'; import { IterableEntryBase } from '../base'; import * as console from 'console'; +import { DFSOperation, DFSStackItem } from '../../types'; /** * Represents a node in a binary tree. @@ -1373,8 +1374,7 @@ export class BinaryTree< callback?: C, pattern?: DFSOrderPattern, beginRoot?: R | BTNKeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: false + iterationType?: IterationType ): ReturnType[]; dfs>( @@ -1382,7 +1382,7 @@ export class BinaryTree< pattern?: DFSOrderPattern, beginRoot?: R | BTNKeyOrNodeOrEntry, iterationType?: IterationType, - includeNull?: true + includeNull?: boolean ): ReturnType[]; /** @@ -1422,90 +1422,7 @@ export class BinaryTree< ): ReturnType[] { beginRoot = this.ensureNode(beginRoot); if (!beginRoot) return []; - const ans: ReturnType[] = []; - if (iterationType === 'RECURSIVE') { - const dfs = (node: OptBTNOrNull) => { - switch (pattern) { - case 'IN': - if (includeNull) { - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); - this.isNodeOrNull(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); - } else { - if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); - this.isRealNode(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); - } - break; - case 'PRE': - if (includeNull) { - this.isNodeOrNull(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); - } else { - this.isRealNode(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); - if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); - } - break; - case 'POST': - if (includeNull) { - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); - this.isNodeOrNull(node) && ans.push(callback(node)); - } else { - if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); - if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); - this.isRealNode(node) && ans.push(callback(node)); - } - - break; - } - }; - - dfs(beginRoot); - } else { - // 0: visit, 1: print - const stack: { opt: 0 | 1; node: OptBTNOrNull }[] = [{ opt: 0, node: beginRoot }]; - - while (stack.length > 0) { - const cur = stack.pop(); - if (cur === undefined || this.isNIL(cur.node)) 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': - cur.node && stack.push({ opt: 0, node: cur.node.right }); - stack.push({ opt: 1, node: cur.node }); - cur.node && stack.push({ opt: 0, node: cur.node.left }); - break; - case 'PRE': - 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 }); - cur.node && stack.push({ opt: 0, node: cur.node.right }); - cur.node && stack.push({ opt: 0, node: cur.node.left }); - break; - default: - cur.node && stack.push({ opt: 0, node: cur.node.right }); - stack.push({ opt: 1, node: cur.node }); - cur.node && stack.push({ opt: 0, node: cur.node.left }); - break; - } - } - } - } - - return ans; + return this._dfs(callback, pattern, beginRoot, iterationType, includeNull); } bfs>( @@ -2004,6 +1921,163 @@ export class BinaryTree< display(beginRoot); } + protected _dfs>( + callback?: C, + pattern?: DFSOrderPattern, + beginRoot?: R | BTNKeyOrNodeOrEntry, + iterationType?: IterationType + ): ReturnType[]; + + protected _dfs>( + callback?: C, + pattern?: DFSOrderPattern, + beginRoot?: R | BTNKeyOrNodeOrEntry, + iterationType?: IterationType, + includeNull?: boolean + ): ReturnType[]; + + /** + * Time complexity: O(n) + * Space complexity: O(n) + */ + + /** + * Time complexity: O(n) + * Space complexity: O(n) + * + * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback + * function on each node according to a specified pattern and iteration type. + * @param {C} callback - The `callback` parameter is a function that will be called for each node + * visited during the depth-first search. It takes a node as an argument and returns a value. The + * return type of the callback function is determined by the generic type `C`. + * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter determines the order in which the + * nodes are visited during the depth-first search. It can have one of the following values: + * @param {R | BTNKeyOrNodeOrEntry} beginRoot - The `beginRoot` parameter is the starting + * point of the depth-first search. It can be either a node object, a key-value pair, or a key. If it + * is a key or key-value pair, the method will find the corresponding node in the tree and start the + * search from there. + * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter determines the + * type of iteration to use during the depth-first search. It can have two possible values: + * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines + * whether or not to include null values in the depth-first search traversal. If `includeNull` is set + * to `true`, null values will be included in the traversal. If `includeNull` is set to `false`, null + * values will + * @returns an array of the return types of the callback function. + */ + protected _dfs>>( + callback: C = this._DEFAULT_CALLBACK as C, + pattern: DFSOrderPattern = 'IN', + beginRoot: R | BTNKeyOrNodeOrEntry = this.root, + iterationType: IterationType = this.iterationType, + includeNull = false + ): ReturnType[] { + beginRoot = this.ensureNode(beginRoot); + if (!beginRoot) return []; + const ans: ReturnType[] = []; + if (iterationType === 'RECURSIVE') { + const visitNullableLeft = (node: OptBTNOrNull) => { + if (node && this.isNodeOrNull(node.left)) dfs(node.left); + }; + const visitLeft = (node: OptBTNOrNull) => { + if (node && this.isRealNode(node.left)) dfs(node.left); + }; + const visitNullableRight = (node: OptBTNOrNull) => { + if (node && this.isNodeOrNull(node.right)) dfs(node.right); + }; + const visitRight = (node: OptBTNOrNull) => { + if (node && this.isRealNode(node.right)) dfs(node.right); + }; + + const dfs = (node: OptBTNOrNull) => { + switch (pattern) { + case 'IN': + if (includeNull) { + visitNullableLeft(node); + ans.push(callback(node)); + visitNullableRight(node); + } else { + visitLeft(node); + ans.push(callback(node)); + visitRight(node); + } + break; + case 'PRE': + if (includeNull) { + ans.push(callback(node)); + visitNullableLeft(node); + visitNullableRight(node); + } else { + ans.push(callback(node)); + visitLeft(node); + visitRight(node); + } + break; + case 'POST': + if (includeNull) { + visitNullableLeft(node); + visitNullableRight(node); + ans.push(callback(node)); + } else { + visitLeft(node); + visitRight(node); + ans.push(callback(node)); + } + break; + } + }; + + dfs(beginRoot); + } else { + const stack: DFSStackItem[] = [{ opt: DFSOperation.VISIT, node: beginRoot }]; + const pushLeft = (cur: DFSStackItem) => { + cur.node && stack.push({ opt: DFSOperation.VISIT, node: cur.node.left }); + }; + const pushRight = (cur: DFSStackItem) => { + cur.node && stack.push({ opt: DFSOperation.VISIT, node: cur.node.right }); + }; + const pushParent = (cur: DFSStackItem) => { + stack.push({ opt: DFSOperation.PROCESS, node: cur.node }); + }; + while (stack.length > 0) { + const cur = stack.pop(); + if (cur === undefined) continue; + if (includeNull) { + if (!this.isNodeOrNull(cur.node)) continue; + } else { + if (!this.isRealNode(cur.node)) continue; + } + if (cur.opt === 1) { + ans.push(callback(cur.node)); + } else { + switch (pattern) { + case 'IN': + pushRight(cur); + pushParent(cur); + pushLeft(cur); + break; + case 'PRE': + pushRight(cur); + pushLeft(cur); + pushParent(cur); + break; + case 'POST': + pushParent(cur); + pushRight(cur); + pushLeft(cur); + break; + default: + pushRight(cur); + pushParent(cur); + pushLeft(cur); + break; + } + } + } + } + + return ans; + } + /** * Time Complexity: O(1) * Space Complexity: O(1) diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 5788820..6adaa0e 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -557,7 +557,7 @@ export class BST< beginRoot: R | BTNKeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): ReturnType[] { - return super.dfs(callback, pattern, beginRoot, iterationType, false); + return super.dfs(callback, pattern, beginRoot, iterationType); } /** diff --git a/src/types/data-structures/binary-tree/binary-tree.ts b/src/types/data-structures/binary-tree/binary-tree.ts index d367b29..b61b2ae 100644 --- a/src/types/data-structures/binary-tree/binary-tree.ts +++ b/src/types/data-structures/binary-tree/binary-tree.ts @@ -28,4 +28,11 @@ export type BTNPureKeyOrNodeOrEntry = [K, OptValue] | BTNPureKeyO export type BinaryTreeDeleteResult = { deleted: OptBTNOrNull; needBalanced: OptBTNOrNull }; -export type BTNCallback = (node: NODE) => D; \ No newline at end of file +export type BTNCallback = (node: NODE) => D; + +export enum DFSOperation { + VISIT = 0, + PROCESS = 1, +} + +export type DFSStackItem = { opt: DFSOperation; node: OptBTNOrNull } \ No newline at end of file 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 3900305..423f1dc 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -292,29 +292,178 @@ describe('BinaryTree', () => { expect(tree.getNodes(tree.getNodeByKey(2), undefined, false, tree.root)).toEqual([tree.getNodeByKey(2)]); }); + it('should tree traverse', () => { + tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]); + expect(tree.dfs(node => node.key, 'PRE', undefined, 'ITERATIVE')).toEqual([4, 2, 1, 5, 6, 3, 7]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'ITERATIVE', false)).toEqual([ + 4, 2, 1, 5, 6, 3, 7 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'ITERATIVE', true)).toEqual([ + 4, + 2, + null, + 1, + 5, + null, + 6, + 3, + 7, + null + ]); + + expect(tree.dfs(node => node.key, 'PRE', undefined, 'RECURSIVE')).toEqual([4, 2, 1, 5, 6, 3, 7]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'RECURSIVE', false)).toEqual([ + 4, 2, 1, 5, 6, 3, 7 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'RECURSIVE', true)).toEqual([ + 4, + 2, + null, + 1, + 5, + null, + 6, + 3, + 7, + null + ]); + + expect(tree.dfs(node => node.key, 'IN', undefined, 'ITERATIVE')).toEqual([2, 5, 1, 4, 7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'ITERATIVE', false)).toEqual([ + 2, 5, 1, 4, 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'ITERATIVE', true)).toEqual([ + null, + 2, + 5, + 1, + null, + 4, + 7, + 3, + 6, + null + ]); + + expect(tree.dfs(node => node.key, 'IN', undefined, 'RECURSIVE')).toEqual([2, 5, 1, 4, 7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'RECURSIVE', false)).toEqual([ + 2, 5, 1, 4, 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'RECURSIVE', true)).toEqual([ + null, + 2, + 5, + 1, + null, + 4, + 7, + 3, + 6, + null + ]); + + expect(tree.dfs(node => node.key, 'POST', undefined, 'ITERATIVE')).toEqual([5, 1, 2, 7, 3, 6, 4]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'ITERATIVE', false)).toEqual([ + 5, 1, 2, 7, 3, 6, 4 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'ITERATIVE', true)).toEqual([ + null, + 5, + null, + 1, + 2, + 7, + 3, + null, + 6, + 4 + ]); + + expect(tree.dfs(node => node.key, 'POST', undefined, 'RECURSIVE')).toEqual([5, 1, 2, 7, 3, 6, 4]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'RECURSIVE', false)).toEqual([ + 5, 1, 2, 7, 3, 6, 4 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'RECURSIVE', true)).toEqual([ + null, + 5, + null, + 1, + 2, + 7, + 3, + null, + 6, + 4 + ]); + }); + it('should sub tree traverse', () => { tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]); expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]); - expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE', false)).toEqual([6, 3, 7]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', false)).toEqual([ + 6, 3, 7 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([ + 6, + 3, + 7, + null + ]); + expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'RECURSIVE')).toEqual([6, 3, 7]); - expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([ + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', false)).toEqual([ + 6, 3, 7 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', true)).toEqual([ 6, 3, 7, null ]); - expect(tree.dfs(node => (node ? node.key : node), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([ - 6, - 3, + + expect(tree.dfs(node => node.key, 'IN', tree.getNode(6), 'ITERATIVE')).toEqual([7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'ITERATIVE', false)).toEqual([ + 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'ITERATIVE', true)).toEqual([ 7, + 3, + 6, null ]); - expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', true)).toEqual([ - 6, - 3, + + expect(tree.dfs(node => node.key, 'IN', tree.getNode(6), 'RECURSIVE')).toEqual([7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'RECURSIVE', false)).toEqual([ + 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'RECURSIVE', true)).toEqual([ 7, + 3, + 6, null ]); + + expect(tree.dfs(node => node.key, 'POST', tree.getNode(6), 'ITERATIVE')).toEqual([7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'ITERATIVE', false)).toEqual([ + 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'ITERATIVE', true)).toEqual([ + 7, + 3, + null, + 6 + ]); + + expect(tree.dfs(node => node.key, 'POST', tree.getNode(6), 'RECURSIVE')).toEqual([7, 3, 6]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'RECURSIVE', false)).toEqual([ + 7, 3, 6 + ]); + expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'RECURSIVE', true)).toEqual([ + 7, + 3, + null, + 6 + ]); }); it('should clear the tree', () => {