简体   繁体   中英

Javascript: Binary Search Tree in order traversal recursive confusion

given the code below, I am bit confused as to how the order of operations happens to get an in order traversal of a binary search tree.

BinarySearchTree.prototype.inOrder = function() {
    if (this.root == null) {
      return null;
    } else {
      var result = new Array();
      function traverseInOrder(node) {       
        node.left && traverseInOrder(node.left);
        result.push(node.data);
        node.right && traverseInOrder(node.right);
      }
      traverseInOrder(this.root);
      return result;
    };
}

I tried to add a debugger statement and follow but I get lost inside:

  function traverseInOrder(node) {       
    node.left && traverseInOrder(node.left); //step 1
    result.push(node.data);  //step 2
    node.right && traverseInOrder(node.right); //step 3
  }

node.left && traverseInOrder(node.left); (Step 1) gets run then gets run again then gets run again. Finally when there is no node.left , Step 2 gets called: result.push(node.data);
This is the part where it loses me . Now it tries to run node.right && traverseInOrder(node.right) but there is no node.right but instead of moving out of the function, it goes back up to Step 2, result.push(node.data); .

Is this queued up from the multiple recursive calls in Step 1?

Let's look at an example. Let it be the below tree which will be traversed in order .

在此处输入图像描述

  • The first traverseInOrder is called with this.root , it means the parameter from the above example is A . The node.left exists, it follows traverseInOrder is called with parameter B .
    • In the call of B the node.left exists, it follows traverseInOrder is called with parameter D .
      • In the call of D node.left does not exist ( node.left is falsy), so result.push(node.data); is called with parameter D . In the next step node.right is falsy, it follows the traversInOrder with parameter D is finished. We get back to the B .
    • We are back to call B , and because the traversInOrder with D just finished, result.push(node.data) will be called with parameter B . And as next node.right is truthy so traverseInOrder is called with the node.right so with E .
      • At E node.left is falsy, result.push is called with parameter E . node.right is falsy is the call with E ended here. We get back to call A , because as we return from here to the call of B it finishes at this point.
  • At call with parameter A we just finished the left node, result.push(node.data); is called for A and next node.right is truthy so result.push(node.data) is called with the right node witch means parameter C .

And it goes on the same with the C,F,G.

tenkmilan already did an excellent job of showing how to envision that code.

Here I go a different path, and write a simpler inorder traversal. It should be fairly clear how that can map to the code supplied.

An inorder traversal is simple enough. preorder and postorder are the other most common tree traversals and they work on arbitrary finite trees. Inorder is only defined for binary trees, and uses the left - and right -children of your node. The traversal order is to (recursively) traverse the left child, then visit the node itself, and finally to (recursively) traverse the right child.

We can write such a traversal simply:

const inorder = (tree) =>
  tree 
    ? [
        ... inorder (tree .left),
        tree .data,
        ... inorder (tree .right)
      ]
    : []

We have a base-case where the node we're looking at is empty, and we just return an empty array. In the general case we just concatenate together a recursive call on left.tree with our current node's value and a recursive call on right.tree .

That's all there is to inorder traversal. You can see it in action in this snippet:

 const inorder = (tree) => tree? [... inorder (tree.left), tree.data, ... inorder (tree.right) ]: [] const tree = { data: 'F', left: { data: 'B', left: {data: 'A'}, right: { data: 'D', left: {data: 'C'}, right: {data: 'E'} } }, right: { data: 'H', left: {data: 'G'}, right: {data: 'I'} } } console.log (inorder (tree))

Of course, this is for a simple tree stored as a plain JS object. But mapping back your sample code is easy enough. I'm guessing that if you can follow this one, you can quickly follow that one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM