如何以递归方式构建树中每个节点的路径 - JavaScript?

时间:2017-10-23 15:13:21

标签: javascript recursion path tree

我的数据结构如下所示:

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

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

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

例如id:3的路径为1> 2> 3 id:2将具有1> 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);
    }

  }

}

3 个答案:

答案 0 :(得分:1)

除了不明确涉及父母的不明确之外,您可以将路径存储为arrray并将其用于每个嵌套迭代。

&#13;
&#13;
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);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:1)

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

&#13;
&#13;
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)
&#13;
&#13;
&#13;

答案 2 :(得分:1)

你犯了一个错误

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

这使得你的程序不一致且不必要地复杂来处理根节点差异 - 解决方案是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: [ ] } ] } ] }