【问题标题】:How to build the path to each node in a tree recursively - JavaScript?如何递归地构建树中每个节点的路径 - JavaScript?
【发布时间】:2018-04-04 04:55:24
【问题描述】:

我的数据结构将如下所示:

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

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

我的目标是为每个节点建立一条路径。

例如 id: 3 的路径为 1 > 2 > 3 id: 2 的路径为 1 > 2

我想通过算法运行我的树,所以它会被这样修改:

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

我编写了一个算法,它将访问树中的所有节点: https://plnkr.co/edit/CF1VNofzpafhd1MOMVfj

如何构建每个节点的路径?

这是我的尝试:

function traverse(branch, parent) {

  for (var i = 0; i < branch.length; i++) {

    branch[i].visited = true;

    if (branch[i].path === undefined) {
      branch[i].path = [];
    }

    if (parent != null) {
      branch[i].path.push(parent);
    }

    if (branch[i].children.length > 0) {
      traverse(branch[i].children, branch[i].id);
    }

  }

}

【问题讨论】:

  • 为什么在开始时 id = 2 的路径为 '1'?为什么路径字符串的值是?
  • 在这个阶段它们没有必要成为字符串。它们最终将被输出到视图中。哦,对不起,你是正确的 2 不是 1 的子节点。

标签: javascript recursion path tree


【解决方案1】:

除了不直接涉及的父级的不明确获取之外,您可以将路径存储为数组并为每个嵌套迭代获取它。

function iter(path) {
    path = path || [];
    return function (o) {
        o.path = path.concat(o.id);
        if (o.children) {
            o.children.forEach(iter(o.path));
        }
    }
}

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

tree.forEach(iter());
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 效果很好。你能解释一下为什么你的答案可能更高效等吗?
  • 为了提高性能,实际上您需要使用for 循环,但将来可能会更快。你有多少个节点?
【解决方案2】:

您可以为此使用递归并检查输入数据是数组还是常规对象。

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

function paths(tree, parent = []) {
  if (Array.isArray(tree)) {
    tree.forEach(e => paths(e, parent))
  } else if (typeof tree == 'object') {
    parent = parent.concat(tree.id)
    tree.path = parent;
    if (tree.children) paths(tree.children, parent)
  }
}

paths(tree)
console.log(tree)

【讨论】:

    【解决方案3】:

    你犯了一个错误

    你的根节点是一个数组,但所有其他节点都是对象

    这会使您的程序不一致,并且处理根节点差异时不必要地复杂-解决方案是stop writing data using literals-您肯定会像上面那样犯错误

    相反,只需制作一些简单的数据构造函数,您的复杂性就会烟消云散

    const Node = (id, ...children) =>
      ({ id, children })
    
    const PathNode = (id, path, ...children) =>
      ({ id, path, children })
    
    const addPaths = ({id, children}, acc = []) =>
      PathNode (id, acc, children.map (child =>
        addPaths (child, [...acc, id])))
        
    const tree =
      Node (0, Node (1),
               Node (2, Node (3)))
    
    console.log (tree)
    // { id: 0, children: [
    //   { id: 1, children: [ ] },
    //   { id: 2, children: [
    //     { id: 3, children: [ ] } ] } ] }
    
    console.log (addPaths (tree))
    // { id: 0, path: [ ], children: [
    //   { id: 1, path: [ 0 ], children: [ ] },
    //   { id: 2, path: [ 0 ], children: [
    //     { id: 3, path: [ 0, 2 ], children: [ ] } ] } ] }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 2021-02-09
      • 1970-01-01
      • 2011-07-12
      • 2013-01-14
      相关资源
      最近更新 更多