我正在尝试迭代一个递归对象,但Java并不支持我所知道的。
例如,给定对象Item
:
public class Item {
Long uuid;
List<Item> children;
}
使用for
循环,我可以遍历children
,但由于children
将包含更多children
,其中包含更多children
等等,所以没有根据深度自动确定深度和循环的方法。
有没有办法迭代递归对象?
答案 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应该是空的,因此它会终止该迭代。
希望这有帮助。