3

I want to do a depth-first traversal for this binary tree:

          1
         / \
        4   5
       / \   \
      4   4   5

Here's the node structure:

function TreeNode(data){
    this.data = data
    this.left = this.right = []

    this.addLeft = function(node){
        this.left.push(node)
    }

    this.addRight = function(node){
        this.right.push(node)
    }
}

The visit function (just to print out the node data):

function visit(node){
    console.log(node.data)
}

The traverse function:

function traverse(node){
   if(node === null) return

   visit(node)

   //visit left branch
   for(node of node.left) traverse(node)

   //visit right branch
   for(node of node.right) traverse(node)
}

Add the binary tree structure:

let rootNode = new TreeNode(1)
let node_4A = new TreeNode(4)
let node_4B = new TreeNode(4)
let node_4C = new TreeNode(4)
let node_5A = new TreeNode(5)
let node_5B = new TreeNode(5)

//add root node branches
rootNode.addLeft(node_4A)
rootNode.addRight(node_5A)

node_4A.addLeft(node_4B)
node_4A.addRight(node_4C)
node_5A.addRight(node_5B)

The output:

1
4
4
4
5
5
5

So it correctly prints out the node data, but there's always an additional right-most node that got printed twice (i.e. the last 5). Do you have any idea why it happens?

I'm not too familiar with Javascript call stack, but could the reason be I'm running 2 for loops in a recursive function?

Thank you.

Daniel
  • 437
  • 1
  • 5
  • 14

3 Answers3

3

You take the same object reference for left and right.

this.left = this.right = []

You need independent arrays:

this.left = [];
this.right = [];

For taking the right node, take different names than node for iterating.

function traverse(node) {
    if (!node) return;  // you never have a value of null for a node
    visit(node)

    //visit left branch
    for (let n of node.left) {
        traverse(n);
    }
    //visit right branch
    for (let n of node.right) {
        traverse(n);
    }
}

function TreeNode(data) {
    this.data = data
    this.left = [];
    this.right = [];

    this.addLeft = function (node) {
        this.left.push(node)
    }

    this.addRight = function (node) {
        this.right.push(node)
    }
}

function visit(node) {
    console.log(node.data)
}

function traverse(node) {
    if (!node) return; // you never have a value of null for a node

    visit(node)

    for (let n of node.left) {
        traverse(n);
    }

    for (let n of node.right) {
        traverse(n);
    }
}

let rootNode = new TreeNode(1)
let node_4A = new TreeNode(4)
let node_4B = new TreeNode(4)
let node_4C = new TreeNode(4)
let node_5A = new TreeNode(5)
let node_5B = new TreeNode(5)

//add root node branches
rootNode.addLeft(node_4A)
rootNode.addRight(node_5A)

node_4A.addLeft(node_4B)
node_4A.addRight(node_4C)
node_5A.addRight(node_5B)
traverse(rootNode);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • and the last 5 printed? – Emeeus Jul 31 '18 at 17:16
  • Answer is accepted. Thank you. So I made 2 mistakes, first is using the same reference for `left` and `right` arrays, and second is using the same variable name in the `traverse` function. Is `let` necessary? Because I find that the code runs fine: `for(currentNode of node.left) traverse(currentNode)` I don't use `let`. Would it be a problem later? – Daniel Jul 31 '18 at 17:41
  • No it isnt even a problem right now, but it makes the code unreadable + error prone + hard to maintain in the future – Jonas Wilms Jul 31 '18 at 17:48
1

DFS (depth first search) is usually easy to implement using recursion. refer to this function definition in js language -

    const recFnc = (currNode) => {
      if (currNode !== null) {
        if (currNode.lNode !== null) {
          recFnc(currNode.lNode, lPath);
        }
        if (currNode.rNode !== null) {
          recFnc(currNode.rNode, rPath);
        }
      }
    };

    recFnc(rootNode);

Refer to this class I have created - https://www.npmjs.com/package/@dsinjs/binary-tree and Refer to this function documentation which deals with path calculations and more - https://dsinjs.github.io/binary-tree/#find

0

You do this:

 this.left = this.right = []

So the left leaf is actually the same as the right one. You want:

 this.left = [];
 this.right = [];

Just for fun: This would actually be a good usecase for generators:

 TreeNode.prototype.leftFirst = function*() {
    yield this.data;
    for(const child of this.left.concat(this.right))
       yield* child.leftFirst();
 };

So you can do:

 for(const node of tree.leftFirst())
    console.log(node);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151