如何递归遍历潜在的无限树

Posted

技术标签:

【中文标题】如何递归遍历潜在的无限树【英文标题】:How to recursively traverse a potentially infinite tree 【发布时间】:2022-01-18 16:30:45 【问题描述】:

我有一个对象

Node(String url, List<Node> children);

现在这可能是几个层次,即

Node node1 = new Node ("www.google.com", new List<Node>())) (That list would contain more nodes, etc etc.

我想遍历并展平树,这样我就可以将所有 url 值提取到一个列表中。我认为我需要为此进行递归,但是我不知道该怎么做。

【问题讨论】:

你可以使用也可以不使用递归 【参考方案1】:

您可以编写一个方法,接收Node 并使用递归返回一个节点列表。

public List<Node> flattenNodes(Node node) 
    LinkedList<Node> nodes = new LinkedList<>();
    //recursively add the result of flattening children to nodes list
    node.getChildren().forEach(n -> 
        nodes.addAll(flattenNodes(n));
    );
    //add the current node to nodes list too
    nodes.add(node);
    return nodes;

这假设 Node 类有一个 getChildren 方法来获取节点的子节点作为列表。

这是我在编写此解决方案时使用的节点类:

public class Node 
    private final String url;
    private final List<Node> children;

    public Node(String url, List<Node> children) 
        this.url = url;
        this.children = children;
    

    public List<Node> getChildren() 
        return children;
    

    public String getUrl() 
        return url;
    


我使用以下代码测试了解决方案:

Node aaa = new Node("www.aaa.com", new LinkedList<Node>());
Node aa = new Node("www.aa.com", List.of(aaa));
Node a = new Node("www.a.com", List.of(aa));
Node bb = new Node("www.bb.com", new LinkedList<Node>());
Node b = new Node("www.b.com", List.of(bb));
Node head = new Node("www.google.com", List.of(a, b));

flattenNodes(head).forEach(node -> System.out.println(node.getUrl()));

运行此测试将以下内容打印到控制台:

www.aaa.com
www.aa.com
www.a.com
www.bb.com
www.b.com
www.google.com

【讨论】:

【参考方案2】:

解决此类问题的常用模式与链表的模式类似。 如果你想通过二叉树搜索,那么你可以添加每个节点的左右子节点作为它的类属性,并具有返回这些节点的函数,如下所示:

class Node

  Node leftChild;
  Node rightChild;
  string nodesUrl;

  // make the same function for right child
  public void setLeftChild(Node leftChild)
  
    this.leftChild = leftChild;
  

  // make the same function for right child
  public Node getLeftChild()
  
    return leftChild;
  

  // make here functions for setting and getting the node´s url

由于每个节点都会引用它的子节点,例如,您可以一直到左子节点,直到找到所需的 url。如果你没有成功到达树的末端,你必须尝试你通过的每个节点的每个 rightChild 并重复这个过程。这可以通过递归函数来实现,该函数通常用于搜索树。

Node getNodeWithSearchingUrl(Node rootNode, string searchUrl)

  Node leftChild = rootNode.getLeftChild();
  Node rightChild = rootNode.getRightChild();

  Node foundNode = null;

  if(rootNode != null && rootNode.getUrl().Equals(searchUrl))
  
    return rootNode;
  
  
  if(leftChild != null)
  
    foundNode = getNodeWithSearchingUrl(leftChild, searchUrl);
  
  
  if(foundNode == null && rightChild != null)
  
    foundNode = getNodeWithSearchingUrl(rightChild, searchUrl);     
  

  return foundNode;

我没有尝试该代码,但我认为它应该可以工作。如果您的树不是二元树而是“多级”树,那么您需要将所有孩子保存在一个列表中,并始终使用递归函数遍历整个列表,而不是只保存左右孩子。

【讨论】:

以上是关于如何递归遍历潜在的无限树的主要内容,如果未能解决你的问题,请参考以下文章

php 非递归实现分类树

无限极分类不用递归生成多维数组(树)的方法

sql:如何存储树数据并进行递归遍历(通过查询)?

二叉树遍历和延伸

在C中没有递归和堆栈的遍历树

mysql如何无限极查找最顶层id节点