【问题标题】:Iterate n-levels of linked lists Java迭代n级链表Java
【发布时间】:2017-10-26 13:11:53
【问题描述】:

我有一棵带节点的树,每个节点都包含一个带节点的列表,这些列表中的每个节点都包含节点……它可以有 10 层深,大约有 100 个节点对象。

我尝试迭代以查找所有单个节点对象,但大多数指南都涵盖了二叉树。这简直是压倒性的。如果有人有一些伪代码或者可以指出我正确的方向,我会很高兴。以下课程(抱歉格式错误):

节点

public class Node {
    public String text;
    public LinkedList<Node> nodes;

    public Node() {
        this.nodes = new LinkedList<Node>();
    }

    public Node(String data) {
        this();
        this.text = data;
    }
}

public class Tree {
    public LinkedList<Node> nodes;
    public String text;

    public Tree() {
        nodes = new LinkedList<Node>();
    }

    public Tree(String data) {
        this();
        this.text = data;
    }
}

计划

public class Main {

    public static void main(String[] args) {

        LinkedList<Tree> trees = new LinkedList<Tree>();

        trees.add(new Tree("Root 1"));

        trees.get(0).nodes.add(new Node("Node 1"));
        trees.get(0).nodes.add(new Node("Node 2"));
        trees.get(0).nodes.add(new Node("Node 3"));

        trees.get(0).nodes.get(0).nodes.add(new Node("Node 1:Child 1"));
        trees.get(0).nodes.get(1).nodes.add(new Node("Node 2:Child 1"));
        trees.get(0).nodes.get(2).nodes.add(new Node("Node 3:Child 1"));

        for (Tree tree : trees) {
            tree.nodes.. // find all node-objects
        }
    }
}

【问题讨论】:

    标签: java linked-list tree nodes


    【解决方案1】:

    这可以通过递归来完成。由于您的最大深度为 10 且最大元素 = 100,因此递归不应带来任何性能问题。执行此操作的示例代码:

    List<Node> flattenTree(List<Node> nodes){
        List<Node> allNodes=new LinkedList<>(nodes) ;
        for(Node node:nodes){
            {
               if(node.getNodes()!=null)
               allNodes.addAll(flattenTree(node.getNodes()));
            } 
         return allNodes;
        }
    

    调用它使用:

    List<Node> allNodes = flattenTree(tree.getNodes);
    

    allNodes 将包含这棵树的所有节点。

    【讨论】:

    • 试过这个但是,得到了 ConcurrentModificationException... 一定是做错了什么,但我喜欢你的扁平树的想法 :)
    • 对不起,你是对的。编辑了代码。它现在可以工作了。
    • 这对我有用。我之前自己尝试过递归,但总是以一个永无止境的循环结束,但这段代码完美无缺
    • 很高兴知道...谢谢:)
    【解决方案2】:

    您可以使用递归来做到这一点:

    interface TreeOp {
        void apply(Tree tree);
    }
    

    ...

    void traverse(Tree tree, TreeOp op) {
        op.apply(tree);
        for (Tree child: tree.nodes) {
            traverse(child, op);
        }
    }
    

    ...

    for (Tree tree : trees) {
        traverse(tree, (tree) -> {
           doSomethingWith(tree);
        });
    }
    

    更新:

    其实你可以使用 Consumer 接口而不是定义一个新的接口:

    void traverse(Tree tree, Consumer<Tree> op) {
        op.accept(tree);
        for (Tree child: tree.nodes) {
            traverse(child, op);
        }
    }
    

    更新 2:

    而traverse可以是Tree的一个方法:

    void traverse(Consumer<Tree> op) {
        op.accept(this);
        for (Tree child: nodes) {
            traverse(child, op);
        }
    }
    

    【讨论】:

    • 以前从未使用过消费者,但我也会尝试您的解决方案 :)
    【解决方案3】:

    出于好奇,什么样的问题需要这样的数据结构?

    main 中的类似内容应该会让你走上正轨:

    // set up the master list of all nodes and the list of unvisited nodes
    // with the base tree's node.
    List<Node> allTheNodes = new LinkedList<>();
    allTheNodes.add(tree.node);
    List<Node> unvisited = new LinkedList<>();
    unvisited.add(tree.node);
    
    while (!unvisited.isEmpty())
    {
        // while our unvisited list is not empty, visit the first node in the list
        // and add all of its subnodes to both the list of nodes to visit and the master list of nodes.
        Node currentNode = unvisited.get(0);
        allTheNodes.addAll(currentNode.nodes);
        unvisited.addAll(currentNode.nodes);
        unvisited.remove(currentNode);
    }   
    
    // now, allTheNodes should have all of your nodes in it.
    

    【讨论】:

    • 嗯,也许这不是最好的结构。但是我有产品类别,在每个类别中我都有工具的子类别,其中可以包含相关工具,最后是备件..
    • 哦,我明白了。您应该考虑通过为目录的每个类型或级别创建一个类,然后将成员变量添加到每个类以表示层次结构,从而更容易概念化。通过这样做,您可以有效地将嵌套列表问题变成更具可读性的问题。
    • @Abdil 是的,但工具最多可以有 5 个子级别。所以它是Category->Tools->tools sub1->tools sub2..等等。这是我目前的主要问题。然后可以在每个子级别添加备件,还可以包含备件包->备件等子级别
    • 这是一个棘手的问题。也许树结构可以工作。祝你好运!
    【解决方案4】:

    您只需要跟踪节点的深度:

    LinkedList<Node> currentNodes = new LinkedList<Node>();
    currentNodes.add(root);
    int depth = 0;
    while depth < 10 {
        depth++;
        int size = currentNodes.size();
        for (int i = 0; i < size; i++) {
            Node current = currentNodes.removeFirst();
            //Do something with current
            for (int j = 0; j < current.nodes.size(); j++) {
                currentNodes.addLast(current.nodes.get(j));
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-13
      • 2015-07-14
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多