当前位置: 首页 > 知识库问答 >
问题:

如何收集树结构的所有节点,按深度级别分组?

国高杰
2023-03-14

我有一个带有子节点和父节点的经典树结构。现在,我想收集从最低级别开始按深度分组的所有节点(即按相反顺序),如下所示:

nodes[
  ["A4"],
  ["A3","B3"],
  ["A2","B2","C2"],
  ["A1","B1","C1"],
  ["ROOT"]
];

虽然使用递归遍历方法获取深度级别非常容易,但我想知道是否有任何方法可以在 BFS 或 DFS 搜索中的树遍历期间立即获取深度级别。

我知道我可以在节点插入期间存储深度级别,但由于我要进行大量插入和删除,我更愿意一次性收集按级别分组的整个结构。

另外,我根本不喜欢使用BDS或DFS,两者都很好。这是我的实际代码:

function Node(code, parent) {
  this.code = code;
  this.children = [];
  this.parentNode = parent;
}
Node.prototype.addNode = function (code) {
  var l = this.children.push(new Node(code, this));
  return this.children[l-1];
};
Node.prototype.dfs = function (leafCallback) {
  var stack=[this], n, depth = 0;
  while(stack.length > 0) {
    n = stack.pop();
    if(n.children.length == 0) {
      if(leafCallback) leafCallback(n, this);
       continue;
    }
    for(var i=n.children.length-1; i>=0; i--) {
      stack.push(n.children[i]);
    }
    depth++; // ???
  }
};

var tree = new Node("ROOT");
tree.addNode("A1").addNode("A2").addNode("A3").addNode("A4");
tree.addNode("B1").addNode("B2").addNode("B3");
tree.addNode("C1").addNode("C2");

共有3个答案

东方玉泽
2023-03-14

就是这样-感谢marvel308指出需要额外的助手node.depth

function Node(code, parent) {
  this.code = code;
  this.depth = -1;
  this.children = [];
  this.parentNode = parent;
}

Node.prototype.dfs= function() {
  var result = [], stack = [];
  this.depth = 0;
  stack.push(this);
  while(stack.length > 0) {
    var n = stack[stack.length - 1], i = n.depth;
    if(!result[i]) result.push([]);
    result[i].push(n); /* get node or node.code, doesn't matter */
    stack.length--;
    var children = n.children;
    /* keep the original node insertion order, by looping backward */
    for(var j = n.children.length - 1; j >= 0; j--) {
      var c = children[j];
      c.depth = n.depth + 1;
      stack.push(c);
    }
  }
  return result.reverse(); /* return an array */
};
魏成济
2023-03-14

有可能以递归的方式编写它,这将受益于尾部优化

function reduceTree(tree) {
    const getCode = n => n.code;
    const _reduce = (level = [tree], acc = [[getCode(tree)]], depth = 1) => {
        const children = level.reduce((a, e) => a.concat(e.children), []);
        if (!children.length) {
            return acc;
        }
        acc[depth] = children.map(getCode);
        return _reduce(children, acc, depth + 1);
    };
    return _reduce().reverse();
}

reduceTree(tree);
/*
[
    ["A4"],
    ["A3", "B3"],
    ["A2", "B2", "C2"],
    ["A1", "B1", "C1"],
    ["ROOT"]
]
*/
漆雕恺
2023-03-14

您可以使用递归并传递节点和深度作为参数

function Node(code, parent) {
  this.code = code;
  this.children = [];
  this.parentNode = parent;
}
Node.prototype.addNode = function (code) {
  var l = this.children.push(new Node(code, this));
  return this.children[l-1];
};

let result = [], depth = {};
function dfs(node){
    node.depth = 0;
    let stack = [node];
    while(stack.length > 0){
        let root = stack[stack.length - 1];
        let d = root.depth;
        result[d] = result[d] || [];
        result[d].push(root.code);
        stack.length--;
        for(let element of root.children){
            element.depth = root.depth + 1;
            stack.push(element);
        }
    }
}

var tree = new Node("ROOT");
tree.addNode("A1").addNode("A2").addNode("A3").addNode("A4");
tree.addNode("B1").addNode("B2").addNode("B3");
tree.addNode("C1").addNode("C2");

dfs(tree);

console.log(result.reverse());
 类似资料:
  • 问题内容: 表-用户 列-(userId,name,managerId) 行- 如果我提供用户ID,则应列出所有向他报告的人。如果我给userId = 2,则应返回3,4。 这个查询正确吗 有什么有效的方法来管理DB中的树结构吗?左右叶方式怎么样? 问题答案: 在我看来,邻接列表模型的问题在于,在SQL中很难处理它,尤其是当您不知道树结构的嵌套深度时。 您提到的“左右叶方式”可能是嵌套集合模型,它

  • 如何计算二叉树中最小级别所有叶节点的总和。如果不存在树,则应返回-1。 例子: 对于上述二叉树,返回100(40 60) (图片来源:Geeksforgeks)

  • 给定一个实现为根节点的泛型树,该根节点具有子节点列表,子节点是节点,并且每个节点都具有其子节点列表。 节点具有其子节点的列表: 也有他们儿子的名单:;;; 我将解释我的算法的想法,你可以修复它或给我另一个全新的想法。 遍历树,将树的每个节点添加到队列中,或者如果添加的最后一个节点是级别的最后一个节点,则添加一个“null”。Null是队列中的标识符,用于知道级别已结束的位置。我的问题是,我不知道第

  • 假设我在一棵树中有一个节点,我如何获得所有的叶节点,它们的祖先是这个节点?我这样定义了TreeNode:

  • 因此,我有一个基本的树结构,该结构由树节点组成,该树节点链接到具有父级和子级引用的其他树节点。我想创建一个方法,该方法返回一个 Stream,该流从叶节点流式传输到根节点或从根到叶。我已经实现了这个,但我正在寻找一种创建最少对象的解决方案。最好没有。这是我的代码: 这很好,但我的“问题”是,为每个流调用创建了很多对象。 StreamSupport.stream 创建新的 ReferencePipe

  • 我有一个树数据结构,其中每个节点可以有任意数量的子节点,树可以是任何高度的。获取树中所有叶节点的最佳方法是什么?有没有可能比遍历树中的每个路径更好,直到我到达叶节点? 在实践中,树的最大深度通常为 5 左右,树中的每个节点将有大约 10 个子节点。 我对其他类型的数据结构或特殊树持开放态度,这将使获取叶节点特别理想。 我正在使用javascript,但实际上只是在寻找一般建议,任何语言等。 谢啦!