【问题标题】:Finding the objects in a tree of objects between the root and any object在根和任何对象之间的对象树中查找对象
【发布时间】:2018-04-25 13:07:47
【问题描述】:

我有一个典型的树数据结构,如下所示:

[
  {
    data: object,
    subs:
      [ ...other objects... ]
  },
  ...other objects...
]

它可以有任何形状和数量的节点。

我写了一个方法,它应该递归地找到并返回根 r 和给定对象 o 之间的路径(中间对象数组)。 (无论是否包括 ro 我都不在乎)

public getPath(tree: Array<object>, o: object): Array<object> {

  let path: Array<object> = [];

  function f(subtree: Array<object>): void {
    for (let node of subtree) {

      path.push(node['data']);
      if (node['data'] == o) return;
      else if (node['subs'].length > 0) f(node['subs']);
      else path = [];

    }
  }

  f(tree);
  return path;

}

基本上我的想法是

  • 始终将每个对象添加到从 ro 的遍历期间访问的数组中,
  • 如果遍历的路径不是从 ro 的路径,则清空数组,
  • 如果到达 o 则返回应该结束遍历的位置。

结果:

  • 它适用于 r 作为 o,返回 [r]。
  • 它也适用于 r 作为 o 的第一个孩子,返回 [rr 的第一个孩子强>]。
  • 但是对于选择任何其他对象作为o,不仅返回正确路径的对象,还返回树的许多其他对象。

【问题讨论】:

  • 您实际上将所有测试过的项目推送到path,无论它们是否是搜索的对象,即使它们在通往它的好路径中也不行。你应该从@返回一个值987654324@ 并测试结果以了解是否在此子树中找到它,以了解是否添加了路径。注意:将对象与node['data'] == o 进行比较仅在它们是具有相同引用的相同对象时才有效,即使键和值相同,使用此函数并为其提供新创建的对象getPath({a: val}) 也将不起作用。跨度>

标签: javascript typescript recursion tree


【解决方案1】:

您的代码的缺陷是您使用的是全局(无论如何都超出了f 的范围)path 数组。问题是如果节点不匹配,您将清除整个数组,而您应该只删除当前部分。有两种方法可以实现您想要的:首先是让f 接受一个数组path,它会复制并递归传递直到找到对象,另一种最好的方法是利用调用栈(由递归创建):

public getPath(tree: Array<object>, o: object): Array<object> {

    function f(subtree: Array<object>) {                              // I don't know typescript, so specify the return type as (Array<object> or null)
        for (let node of subtree) {
            if (node.data == o) {                                     // if this is the node we're looking for
                return [node];                                        // return an array (which will be our path), here you can either return [] to exclude the matched node (o) or [node] to include it
            } else if(node.subs.length) {                             // not the node we are looking for, but it has children, so let check'em out 
                let result = f(node.subs);                            // result will either be an array (if we recursively found something), or null otherwise
                if(result) {                                          // if we found something, then result will be the path from the current node to the object o (the current node not included)
                    result.unshift(node);                             // we include the current node by pushing it into the result array (pushing it to the first position)
                    return result;                                    // return result (an array) to signal successfulness
                }
            }
        }
        return null;                                                  // the object o not found in this subtree, return null to signal unsuccessfullness. Kind of redundant, because undefined is returned by default, so feel free to remove it
    }

    return f(tree);    
}

【讨论】:

  • 它有效,您的 cmets 非常有帮助,谢谢。一个关于递归的紧凑教程:)我希望它也能帮助其他人。
猜你喜欢
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
  • 2021-06-05
  • 1970-01-01
  • 2014-08-02
  • 1970-01-01
相关资源
最近更新 更多