【问题标题】:Javascript: Binary Search Tree in order traversal recursive confusionJavascript:按顺序遍历递归混淆的二叉搜索树
【发布时间】:2020-07-31 18:10:50
【问题描述】:

鉴于下面的代码,我对操作顺序如何获得二叉搜索树的顺序遍历感到有些困惑。

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;
    };
}

我试图添加一个调试器语句并跟随,但我迷失在里面:

  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);(第 1 步)运行,然后再次运行,然后再次运行。最后,当没有 node.left 时,第 2 步被调用:result.push(node.data);
这是它失去我的部分。现在它尝试运行node.right && traverseInOrder(node.right),但没有node.right,而是没有退出该函数,而是返回到第2步result.push(node.data);

这是从第 1 步中的多个递归调用中排队的吗?

【问题讨论】:

    标签: javascript recursion binary-search-tree


    【解决方案1】:

    让我们看一个例子。让它成为下面将被遍历的树in order

    • 第一个traverseInOrderthis.root调用,这意味着 上例中的参数是Anode.left 存在,它跟在 traverseInOrder 之后,用参数 B 调用。
      • B的调用中,node.left存在,它跟在traverseInOrder后面是用参数D调用的。
        • D的调用中node.left不存在(node.left是假的),所以result.push(node.data);是用参数D调用的。在下一步中node.right 是假的,它遵循traversInOrder 与参数D 完成。我们回到B
      • 我们回来调用B,因为traversInOrderD刚刚完成,result.push(node.data)将被调用参数B。由于下一个node.right 是真实的,所以traverseInOrdernode.right 调用,所以E 被调用。
        • E node.left 是假的,result.push 使用参数 E 调用。 node.right is falsy 与E 的通话到此结束。我们返回调用A,因为当我们从这里返回到调用B 时,它到此结束。
    • 在使用参数A 调用时,我们刚刚完成了左侧节点,result.push(node.data); 被调用为A 并且下一个node.right 是真实的,所以result.push(node.data) 被调用右侧节点巫婆意味着参数C

    C,F,G 也是如此。

    【讨论】:

    • 这太棒了,非常感谢您抽出时间和精力!
    【解决方案2】:

    tenkmilan 已经出色地展示了如何构想该代码。

    这里我另辟蹊径,写一个更简单的inorder遍历。应该很清楚如何映射到提供的代码。

    inorder 遍历很简单。 preorderpostorder 是其他最常见的树遍历,它们适用于任意有限树。 Inorder 仅针对二叉树定义,并使用您节点的left- 和right-children。遍历顺序是(递归)遍历左孩子,然后访问节点本身,最后(递归)遍历右孩子。

    我们可以简单的写出这样的遍历:

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

    我们有一个基本情况,我们正在查看的节点是空的,我们只返回一个空数组。在一般情况下,我们只是将left .tree 的递归调用与我们当前节点的值和right .tree 的递归调用连接在一起。

    这就是inorder 遍历的全部内容。你可以在这个 sn-p 中看到它的实际效果:

    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))

    当然,这是针对存储为普通 JS 对象的简单树。但是映射回您的示例代码很容易。我猜如果你能关注这个,你也可以很快关注那个。

    【讨论】:

    • 这和之前的答案一样精彩!谢谢斯科特!
    • 很棒的例子!
    猜你喜欢
    • 2017-05-08
    • 2020-09-25
    • 2013-05-12
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    相关资源
    最近更新 更多