迭代递归对象

时间:2015-09-07 10:09:02

标签: java

我正在尝试迭代一个递归对象,但Java并不支持我所知道的。

例如,给定对象Item

public class Item {

     Long uuid;
     List<Item> children;
}

使用for循环,我可以遍历children,但由于children将包含更多children,其中包含更多children等等,所以没有根据深度自动确定深度和循环的方法。

有没有办法迭代递归对象?

5 个答案:

答案 0 :(得分:3)

如果树很深,请按照Eran的建议使用先呼吸搜索。如果树很宽,请使用深度优先搜索,如下所示:

class ItemVisitor { 
    public void accept(Item item) {
        // Do something
        for (Item i : item.getChildren()) {
            this.accept(i);
        }
    }
}

编辑:

对于先呼吸搜索,请使用队列并将当前节点的所有子节点附加到其上。

public void visitTree(Item head) {
    Queue<Item> queue = new PriorityQueue<Item>();
    while (queue.size() > 0) {
        Item curr = queue.poll();
        // Do something
        for (Item i : curr.getChildren())
            queue.add(i);
    }
}

答案 1 :(得分:1)

如果您没有父子树中的循环,您可以使用简单的递归函数来确定后代的数量:

public class Item {
    ...

    public int getDescendantCount() {
        int count = 0;
        if (children != null) {
             count += children.size();
             for (Item child : children)
                  count += child.getDescendantCount();
        }
        return count;
    }
}

答案 2 :(得分:1)

类似的东西?

void read(Item item) {
    if (item == null) {
        //do something with the uuid ?
        return;
    } else {
        for (Item i : item.children) {
            read(i);
        }
    }
}

答案 3 :(得分:1)

如果您可以将深度存储为单独的数据项并通过类设计/封装来强制执行,那么您就可以了。

你提出的是某种不确定深度树的节点。您可以实现任何正常的深度优先或广度优先搜索方法;在任何标准数据结构和算法教科书/ Web引用中查找并在Java中实现。在我输入时Eran发布的解决方案是标准的深度优先搜索,如果您使用堆栈(后进先出或LIFO队列),或者如果您使用FIFO队列则使用广度优先搜索。这些是很好的方法,但不是最简单的方法。

最天真的方法是深度优先搜索的简单递归函数:

public void recurseIntoChildren(Item item) {
    if(item.children.size() == 0) {
        // you are now at a leaf node: do something
    }
    for(Item child : item.children) {
        recurseIntoChildren(child);
    }
}

此表单假设您要在叶节点处执行某些操作。如果你正在搜索某些东西,你可以让recurseIntoChildren()在你找到你想要的东西时返回一个特殊值,这样你就可以突破所有其余的递归循环(让它返回null或其他一些值来指示循环应该继续)。如果您想采取其他行动,请根据您的需要进行操作。

这不是最有效的方法(除非编译器将尾递归优化为简单的循环)。

答案 4 :(得分:1)

我不知道该函数的确切目标是什么,但您始终可以通过子项递归循环。

例如

 public void loopChildren(List<Item> items) {
     for (Item i : items) {
         System.out.println(i.uuid);
         loopChildren(i.children);           
     }       
 }

它只是循环直到列表的结尾。如果一个孩子没有孩子,那么List应该是空的,因此它会终止该迭代。

希望这有帮助。