【问题标题】:Binary Tree - Depth-First Traversal二叉树 - 深度优先遍历
【发布时间】:2019-01-08 03:55:42
【问题描述】:

我想对这棵二叉树进行深度优先遍历:

          1
         / \
        4   5
       / \   \
      4   4   5

这是节点结构:

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 === null) return

   visit(node)

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

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

添加二叉树结构:

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)

输出:

1
4
4
4
5
5
5

所以它正确地打印出节点数据,但总是有一个额外的最右边的节点被打印了两次(即最后一个5)。你知道为什么会这样吗?

我对 Javascript 调用堆栈不太熟悉,但可能是因为我在递归函数中运行了 2 个 for 循环吗?

谢谢。

【问题讨论】:

    标签: javascript binary-tree depth-first-search


    【解决方案1】:

    您对左右使用相同的对象引用。

    this.left = this.right = []
    

    你需要独立的数组:

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

    要获取正确的节点,请使用与node 不同的名称进行迭代。

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

    【讨论】:

    • 最后 5 个打印出来了吗?
    • 答案被接受。谢谢你。所以我犯了两个错误,首先是对leftright 数组使用相同的引用,其次是在traverse 函数中使用相同的变量名。 let 有必要吗?因为我发现代码运行良好:for(currentNode of node.left) traverse(currentNode) 我不使用let。以后会不会有问题?
    • 不,它现在甚至不是问题,但它使代码不可读+容易出错+将来难以维护
    【解决方案2】:

    你这样做:

     this.left = this.right = []
    

    所以左边的叶子实际上和右边的叶子是一样的。你想要:

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

    只是为了好玩:这实际上是生成器的一个很好的用例:

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

    所以你可以这样做:

     for(const node of tree.leftFirst())
        console.log(node);
    

    【讨论】:

    • 正确。这是我使用相同对象引用的错误。 function之后的*是什么?
    • @daniel 将函数转换为 生成器函数
    【解决方案3】:

    DFS(深度优先搜索)通常很容易使用递归实现。参考js语言中的这个函数定义-

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

    参考我创建的这个类 - https://www.npmjs.com/package/@dsinjs/binary-tree 并参考这个处理路径计算等的函数文档 - https://dsinjs.github.io/binary-tree/#find

    【讨论】:

      猜你喜欢
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多