JavaScript - 如何在节点搜索中返回树的分支?

时间:2017-10-20 20:52:50

标签: javascript algorithm recursion tree

我的数据结构如下所示:

var tree = [
    {
        id: 1,
        children: []
    }, {
        id: 2,
        children: [
            {
                id: 3,
                children: []
            }
        ]
    }
];

一个分支上可以有任意数量的节点或子节点。

我的目标是从顶层(根)节点开始,搜索给定节点并返回它所在的分支。

所以在Plunker的例子中:https://plnkr.co/edit/PyR3H7mM0vrFyno1l7R5?p=catalogue

我想搜索节点ID#31,因此算法将返回31属于的数组(分支)。

我已经启动了算法但是如果我递归地执行它,我不知道如何再次回溯。

function traverse(branch) {

  for (var i = 0; i < branch.length; i++) {
    if (branch[i].id == node.id) {
      return branch;
    }
  }

  for (var j = 0; j < branch.length; j++) {
    if (branch[j].children.length > 0) {
      return traverse(branch[j].children);
    }
  }

}

console.log(traverse(tree));

例如,如果我查看最后一个子节点而没有找到匹配项,那么我需要回溯到父分支以尝试下一组选项。

如何修改我的算法以再次回溯?

3 个答案:

答案 0 :(得分:1)

您的算法非常接近,您只需要添加if语句,以便只有在找到匹配项时才返回traverse的递归结果:

function traverse(branch) {

  for (var i = 0; i < branch.length; i++) {
    if (branch[i].id == node.id) {
      return branch;
    }
  }

  for (var j = 0; j < branch.length; j++) {
    var result = traverse(branch[j].children);
    if (result !== undefined) {
      return result;
    }
  }

  return undefined; // no match found

}

console.log(traverse(tree));

答案 1 :(得分:1)

您可以使用临时变量作为子项的结果,如果值是真实的,则退出循环。

function traverse(branch) {
    var result;
    for (var i = 0; i < branch.length; i++) {
        if (branch[i].id === node.id) {
            return branch;
        }
        if (branch[j].children.length > 0) {
            result = traverse(branch[j].children);
            if (result) {
                return result;
            }
        }
    }
}

答案 2 :(得分:0)

这就是返回分支而不是节点本身的技巧:

    function traverse(branch) {

        for (var i = 0; i < branch.length; i++) {
            if (branch[i].id == node.id) {
                return branch[i].children;
            }
        }

        for (var j = 0; j < branch.length; j++) {
            var result = traverse(branch[j].children);
            if (result !== null) {
                return result;
            }
        }

        return null; // no match found
    }