2017-10-20 73 views
0

我的数据结构是这样的:JavaScript - 如何在节点搜索中返回树的分支?

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

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

如何修改我的算法以重新找回?

+0

什么,你想退回,如果没有找到匹配?如果发现某些东西,你只应该返回递归调用的结果。 – 4castle

+0

在我的情况下,总会找到一场比赛,因为我打算让用户点击其中一个来启动搜索过程。 – user1261710

+0

当然,但如果你想让你的代码递归,你必须期望树的每一个分支都不会包含匹配,所以你必须在这些情况下返回一些东西。 – 4castle

回答

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

如何修改算法,以便找到多个匹配而不是一个? – user1261710

+0

您不需要在循环中返回'''',你需要''push'到'results'数组中,然后在最后返回'results'。 – 4castle

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