How to build the path to each node in a tree recursively - JavaScript?

核能气质少年 提交于 2021-01-27 23:07:13

问题


My data structure will look like this:

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

There can be any number of nodes or children on one branch.

My goal is to build a path to every node.

For example id: 3 will have a path of 1 > 2 > 3 id: 2 will have a path of 1 > 2

I want to run my tree through the algorithm so it will be modified like this:

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

I have written an algorithm that will visit all of the nodes in the tree: https://plnkr.co/edit/CF1VNofzpafhd1MOMVfj

How can I build the path to each node?

Here is my attempt:

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

  }

}

回答1:


Beside the unclear taking of not directly involved parents, you could store the path as arrray and take it for each nested iteration.

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



回答2:


You can use recursion for this and check if input data is array or regular object.

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:


You made a mistake

Your root node is an array, but all other nodes are objects.

This makes your program inconsistent and needlessly complex to handle the root node difference – the solution is to stop writing data using literals – you're bound to make mistakes like you did above

Instead, just make some simple data constructors and your complexities vanish into thin air

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


来源:https://stackoverflow.com/questions/46892807/how-to-build-the-path-to-each-node-in-a-tree-recursively-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!