简体   繁体   English

在具有多个子节点的树中打印从根到给定节点的路径

[英]Print path from root to a given node in a tree with multiple children

I am trying to print the path from root to a given node containing value of 2. Each node can have children containing several nodes.我正在尝试打印从根到包含值为 2 的给定节点的路径。每个节点可以有包含多个节点的子节点。 Here is a visual reference这是一个视觉参考

I have flight data like this:我有这样的航班数据:

const flightsTree = {
  departureAirportId: 1,
  flights: [
    {
      departureAirportId: 16,
      flights: [
        { departureAirportId: 8 },
        { departureAirportId: 17 },
        { departureAirportId: 2 },
        { departureAirportId: 11 },
        {
          departureAirportId: 10,
          flights: [
            {
              departureAirportId: 17,
              flights: [{ departureAirportId: 99 }, { departureAirportId: 2 }],
            },
            { departureAirportId: 2 },
          ],
        },
        { departureAirportId: 2 },
        { departureAirportId: 6 },
        { departureAirportId: 3 },
      ],
    },
  ],
};

This is the code I wrote so far:这是我到目前为止写的代码:

const hasPath = (data, path, from) => {
  if (!data) {
    return false;
  }
  path.push(data.departureAirportId);
  if (data.departureAirportId === from) {
    return true;
  }
  if (data.flights) {
    data.flights.forEach((pRule) => {
      hasPath(pRule, path, from);
      return true;
    });
  } else {
    path.pop();
    return false;
  }
  return path;
};

console.log(hasPath(flightsTree, [], 2));

So far I'm getting:到目前为止,我得到:

[1, 16, 2, 10, 17, 2, 2, 2]

It seems like it is able to find the node containing the value but not to print the root path except for the first finding.似乎它能够找到包含该值的节点,但除了第一个发现之外,不能打印根路径。

Thanks a lot for your help.非常感谢你的帮助。

This version first calculates all routes and then filter for those that end with the given location.此版本首先计算所有路线,然后过滤以给定位置结尾的路线。 The second part is trivial.第二部分很琐碎。 The first is a simple recursion;第一个是简单的递归; when the route has no flights, we simply return an array consisting of an array holding the departure airport.当路线没有航班时,我们只需返回一个数组,该数组由一个包含出发机场的数组组成。 When it has flights, we recur on those and to each of the results, we prepend our current departure airport:当它有航班时,我们会重复这些航班,并且对于每个结果,我们都会在我们当前的出发机场前面添加:

 const routes = ({departureAirportId, flights = []}) => flights.length == 0? [[departureAirportId]]: flights.flatMap (routes).map (r => [departureAirportId, ...r]) const endingAt = (loc, flights) => routes (flights).filter (r => r [r.length - 1] == loc) const flightsTree = {departureAirportId: 1, flights: [{departureAirportId: 16, flights: [{departureAirportId: 8}, {departureAirportId: 17}, {departureAirportId: 2}, {departureAirportId: 11}, {departureAirportId: 10, flights: [{departureAirportId: 17, flights: [{departureAirportId: 99}, {departureAirportId: 2}]}, {departureAirportId: 2}]}, {departureAirportId: 2}, {departureAirportId: 6}, {departureAirportId: 3}]}]} console.log (endingAt (2, flightsTree))
 .as-console-wrapper {max-height: 100%;important: top: 0}

There are two assumptions here.这里有两个假设。 The first is that you want only those that end at the target airport.第一个是您只想要那些在目标机场结束的人。 If you want all paths that go through airport 2, you can replace endingAt with a function that filters the routes testing if any contain the target.如果您想要go 通过机场 2 的所有路径,您可以将endingAt替换为 function 过滤测试路线(如果有的话)包含目标。

The second is that the order of the results is not that important.第二个是结果的顺序不是那么重要。 This depth-first traversal is simpler, but if the order of the results in your image is important, we can certainly write a breadth-first traversal version.这种深度优先遍历比较简单,但是如果你的图像中结果的顺序很重要,我们当然可以写一个广度优先遍历的版本。

Scott's answer is beautiful.斯科特的回答很漂亮。 I'm going to share an approach using generators because often times problems like these involve only finding one or some known amount of solutions.我将分享一种使用生成器的方法,因为此类问题通常只涉及找到一个或一些已知数量的解决方案。 Generators allow us to stop computation early instead of computing all routes.生成器允许我们提前停止计算,而不是计算所有路线。 Notice the similarity between the structure of the generator approach and Scott's program -请注意生成器方法的结构与 Scott 的程序之间的相似之处 -

 function* routes ({departureAirportId, flights = []}, r = []) { if (flights.length === 0) yield [...r, departureAirportId] else for (const q of flights) yield* routes(q, [...r, departureAirportId]) } function* endingAt (t, loc) { for (const r of routes(t)) if(r[r.length - 1] == loc) yield r } const flightsTree = {departureAirportId: 1, flights: [{departureAirportId: 16, flights: [{departureAirportId: 8}, {departureAirportId: 17}, {departureAirportId: 2}, {departureAirportId: 11}, {departureAirportId: 10, flights: [{departureAirportId: 17, flights: [{departureAirportId: 99}, {departureAirportId: 2}]}, {departureAirportId: 2}]}, {departureAirportId: 2}, {departureAirportId: 6}, {departureAirportId: 3}]}]} console.log(Array.from(endingAt(flightsTree, 2)))

The above approach is sound because it decomposes the problem into two separate parts, routes and endingAt .上述方法是合理的,因为它将问题分解为两个独立的部分, routesendingAt However the two functions can be collapsed into one, if you wish -但是,如果您愿意,这两个功能可以合并为一个 -

 function* endingAt (t, loc, r = []) { if (t.flights) for (const q of t.flights) yield* endingAt(q, loc, [...r, t.departureAirportId]) else if (t.departureAirportId == loc) yield [...r, t.departureAirportId] } const flightsTree = {departureAirportId: 1, flights: [{departureAirportId: 16, flights: [{departureAirportId: 8}, {departureAirportId: 17}, {departureAirportId: 2}, {departureAirportId: 11}, {departureAirportId: 10, flights: [{departureAirportId: 17, flights: [{departureAirportId: 99}, {departureAirportId: 2}]}, {departureAirportId: 2}]}, {departureAirportId: 2}, {departureAirportId: 6}, {departureAirportId: 3}]}]} console.log(Array.from(endingAt(flightsTree, 2)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在二叉树中从根到节点的返回路径 - Return path from root to node in a binary tree 从给定节点查找树中父节点的路径 - Find the path to parent node in a tree from a given node 从Javascript Fancy树中的根节点完成路径 - Complete path from the root node in Javascript Fancy tree 获取对象树内给定节点的子代 - Get children of a given node within an object tree 在具有任意数量孩子的树中,查找节点是在给定节点的左半子树还是右半子树中 - In a tree with arbitrary number of children, find whether a node is in the left half subtrees or right half subtrees of a given node 从 d3js 树布局中删除节点及其子节点 - Removing node and its children from d3js tree layout 从d3.js中的树中选择节点的子级 - Select the children of a node from a tree in d3.js 当我单击特定节点并绘制通往其子叶的路径时,是否有用于着色或突出显示树枝的 ECharts 选项? - Is there an ECharts option for coloring or highlight tree branch when I clicked a specific node and draw a path up to their children leaves? 如何从树对象获取给定路径的子树? - How to get a subtree given a path from a tree object? 当一个父母有多个使用nodejs的孩子时,如何打印家谱中的关系? - How to print the relationships in a family tree when one parent has multiple no of children using nodejs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM