【问题标题】:Best algorithm to iterate a parent-child tree structure迭代父子树结构的最佳算法
【发布时间】:2020-01-20 16:36:57
【问题描述】:

我一次又一次地遇到这种情况,我有一个非常简单的解决方案,但我想知道还有哪些其他算法可能更清洁、更易于维护。我的具体用例涉及处理数据管道,我将在其中多次收到此结构并在完成后处理它。我只需要迭代这个结构一次。

假设您有一个具有父子关系的树结构;这是一个没有边界的一对多关系。

public class Node {
    private String name;

    private Boolean resource;

    private Node parent;

    private List<Node> children;

    // getters and setters...
}

假设我想从根节点开始递归搜索这个结构,但是在结构中建立所有节点的索引的开销大于它的价值。我可能会这样写:

private static Node getNodeByName(Node node, String name) {
    if (node.getName().equals(name)) {
        return node;

    } else if (!node.getChildren().isEmpty()) {
        for (Node node : node.getChildren()) {
            Node childNode;

            if ((childNode = getNodeByName(node, name)) != null) {
                return childNode;
            }
        }
    }

    return null;
}

让我们改变需求。现在我们要收集Node 中符合特定条件的List

private static List<Node> getResourceNodes(Node node) {
    List<Node> matchedNodes = new ArrayList<>();
    SomeClass.getResourceNodes(node, matchedNodes);

    return matchedNodes;
}

private static void getResourceNodes(Node node, List<Node> matchedNodes) {
    if (node.isResource())) {
        matchedNodes.add(node);
    }

    if (!node.getChildren().isEmpty()) {
        for (Node node : node.getChildren()) {
            getResourceNodes(node, matchedNodes);
        }
    }
}

我在这里直接写了这些。可能有一两个语法错误。我想知道还有什么其他的方式,也许是更易于维护的方式,这可以被写出来。这就是我一直接近链接节点的方式,现在我很想知道是否有更好的方法。

【问题讨论】:

  • 你想要深度优先还是广度优先?
  • @MichaelBianconi 为了使其与我的示例保持一致,广度优先。
  • @MichaelBianconi 我撤回我原来的评论。毕竟,理解广度优先似乎不适用于我的示例。我想我的方法是深度优先?
  • 我猜这个标准并不总是一样的,是吗?

标签: java tree


【解决方案1】:

如果您正在寻找一种更简洁、更易于维护的算法,请不要通过方法传递列表(向下构建列表)。相反,通过返回它来向上构建列表。

private static List<Node> getResourceNodes(Node node) {

    List<Node> matchedNodes = new ArrayList<>();

    if (node.isResource()) matchedNodes.add(node);

    for (Node child : node.getChildren()) {
        matchedNodes.addAll(getResourceNodes(child);
    }

    return matchedNodes;
}

【讨论】:

  • 谢谢。看起来挺好的。为了可维护性,我还加入了一个Predicate&lt;Node&gt; 参数,它将对isResources() 的调用替换为criterion.test(node)
【解决方案2】:

为了详细说明迈克尔的回答,我还在方法参数中添加了Predicate。为了可维护性,这也应该是 Node 实现的一部分。

public class Node {
    //...

    private List<Node> filter(Predicate<Node> filter) {

        List<Node> matchedNodes = new ArrayList<>();

        if (filter.test(this)) matchedNodes.add(node);

        for (Node child : node.getChildren()) {
            matchedNodes.addAll(node.filter(filter));
        }

        return matchedNodes;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2011-04-15
    • 2017-01-29
    相关资源
    最近更新 更多