From 7a1141b637edcb3bbd3c6f31abfa8d395436f2ec Mon Sep 17 00:00:00 2001 From: k ho k ho? <6939499+kho-kho-kho@users.noreply.github.com> Date: Sun, 25 Sep 2022 01:11:00 -0700 Subject: [PATCH] refactor: BFS tree algorithms (#1108) * Bugfix AVLTree comparator The original insertBalance function was doing raw value comparisons as opposed to using the tree's comparator. This is clearly unintentional, and would (ultimately) cause the structure to segfault when constructed with the stringData included in the updated test. I've added the fix, scanned the rest of the code for similar issues, and added the appropriate test case which passes successfully with the fix. The jest code coverage increases slightly as well with the changes. * 100% jest code coverage Added a couple of extra elements to the original test tree, and then removed elements in an order such that all previously uncovered branches of code are now covered. Also added an emptyTree structure to test some additional (trivial) base cases. * standard style fix missed this from my previous commit * Iterative & in-place BFS An iterative analog to the traditional recursive breadth-first-search algorithm for binary trees. This in-place solution uses the pre-existing "traversal" array for both tracking the algorithm as well as storing the result. Also tweaked old code by resetting the traversal array each time the tree is traversed (otherwise you're only allowed to traverse a tree once which doesn't seem correct even with a single traversal function). * Update BreadthFirstTreeTraversal.js got rid of unnecessary currentSize added currentNode for clarity * refactor out traversal member var .. per earlier discussion w mods also tweaked the tests to achieve 100% coverage --- Trees/BreadthFirstTreeTraversal.js | 31 ++++++++++---------- Trees/test/BreadthFirstTreeTraversal.test.js | 14 ++++++--- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Trees/BreadthFirstTreeTraversal.js b/Trees/BreadthFirstTreeTraversal.js index 10fdc0aeb..a61b3ca17 100644 --- a/Trees/BreadthFirstTreeTraversal.js +++ b/Trees/BreadthFirstTreeTraversal.js @@ -14,34 +14,33 @@ class Node { class BinaryTree { constructor () { this.root = null - this.traversal = [] } breadthFirstIterative () { - this.traversal = [] + const traversal = [] if (this.root) { - this.traversal.push(this.root) + traversal.push(this.root) } - for (let i = 0; i < this.traversal.length; i++) { - const currentNode = this.traversal[i] + for (let i = 0; i < traversal.length; i++) { + const currentNode = traversal[i] if (currentNode.left) { - this.traversal.push(currentNode.left) + traversal.push(currentNode.left) } if (currentNode.right) { - this.traversal.push(currentNode.right) + traversal.push(currentNode.right) } - this.traversal[i] = currentNode.data + traversal[i] = currentNode.data } - return this.traversal + return traversal } breadthFirstRecursive () { - this.traversal = [] + const traversal = [] const h = this.getHeight(this.root) for (let i = 0; i !== h; i++) { - this.traverseLevel(this.root, i) + this.traverseLevel(this.root, i, traversal) } - return this.traversal + return traversal } // Computing the height of the tree @@ -54,15 +53,15 @@ class BinaryTree { return lheight > rheight ? lheight + 1 : rheight + 1 } - traverseLevel (node, levelRemaining) { + traverseLevel (node, levelRemaining, traversal) { if (node === null) { return } if (levelRemaining === 0) { - this.traversal.push(node.data) + traversal.push(node.data) } else { - this.traverseLevel(node.left, levelRemaining - 1) - this.traverseLevel(node.right, levelRemaining - 1) + this.traverseLevel(node.left, levelRemaining - 1, traversal) + this.traverseLevel(node.right, levelRemaining - 1, traversal) } } } diff --git a/Trees/test/BreadthFirstTreeTraversal.test.js b/Trees/test/BreadthFirstTreeTraversal.test.js index a6b795f31..aa1a2795d 100644 --- a/Trees/test/BreadthFirstTreeTraversal.test.js +++ b/Trees/test/BreadthFirstTreeTraversal.test.js @@ -8,7 +8,7 @@ describe('Breadth First Tree Traversal', () => { root.right = new Node(8) root.left.left = new Node(3) root.left.right = new Node(6) - root.right.right = new Node(9) + root.left.right.right = new Node(9) binaryTree.root = root // Visualization : @@ -16,11 +16,17 @@ describe('Breadth First Tree Traversal', () => { // 7 // / \ // 5 8 - // / \ \ - // 3 6 9 + // / \ + // 3 6 + // \ + // 9 + + it('Binary tree - Empty case', () => { + const emptyTree = new BinaryTree() + expect(emptyTree.breadthFirstIterative()).toStrictEqual([]) + }) it('Binary tree - Level order recursive traversal', () => { - expect(binaryTree.traversal).toStrictEqual([]) const traversal = binaryTree.breadthFirstRecursive() expect(traversal).toStrictEqual([7, 5, 8, 3, 6, 9]) })