如何递归地构建树中每个节点的路径 - JavaScript



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

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

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

我的目标是构建通往每个节点的路径。

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

除了不明确获取未直接参与的父项之外,您还可以将路径存储为 arrray 并为每个嵌套迭代获取它。

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

你犯了一个错误

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

这使得你的程序不一致,并且处理根节点差异变得不必要地复杂 - 解决方案是停止使用文字写入数据 - 你一定会犯像上面那样的错误

相反,只需制作一些简单的数据构造函数,您的复杂性就会消失在稀薄的空气中

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: [ ] } ] } ] }

您可以使用

reduce方法创建一个递归函数,并将递归调用中以前的路径值作为id's数组传递。

var tree = [{ id: 1, children: [] }, { id: 2, children: [{ id: 3, children: [] }] }];
function getPaths(data, prev = []) {
  return data.reduce((r, { id, children }) => {
    const o = { id, children, path: [...prev, id] }
    
    if (children) {
      o.children = getPaths(children, o.path)
    }
    
    r.push(o)
    return r
  }, [])
}
console.log(getPaths(tree))

相关内容

  • 没有找到相关文章

最新更新