Java中可自实现LeafIterator类封装DFS遍历逻辑,用栈延迟加载叶子节点,提供标准Iterator<T>接口;构造时压入根节点,hasNext()循环弹栈至叶子或栈空,next()返回并推进,支持空树处理且单次不可重用。

Java 中不能直接用 Iterator 遍历树形结构的叶子节点,因为标准的 Iterator 接口只支持线性、单向遍历;但你可以**自己实现一个叶子节点的迭代器**,封装深度优先(DFS)或广度优先(BFS)遍历逻辑,对外提供标准的 Iterator<T> 接口。
核心思路:延迟加载 + 栈/队列模拟遍历
不一次性把所有叶子节点全找出来存进集合(浪费内存),而是用栈(DFS)或队列(BFS)边走边找,在 next() 调用时才定位下一个叶子节点。这样既符合 Iterator 的惰性语义,又节省空间。
用 DFS 实现叶子迭代器(推荐)
适合大多数场景,代码简洁,能自然保证叶子节点按“最左深度优先”顺序返回。
- 构造时把根节点压入栈
-
hasNext():循环弹栈,直到栈空或遇到叶子节点 -
next():返回当前叶子节点,并继续推进到下一个叶子 - 非叶子节点弹出后,将其子节点(从右往左压栈)以保持左→右顺序
示例(假设树节点定义为 TreeNode<T>,含 List<TreeNode<T>> children):
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public class LeafIterator<T> implements Iterator<T> {
private final Deque<TreeNode<T>> stack = new ArrayDeque<>();
<pre class='brush:java;toolbar:false;'>public LeafIterator(TreeNode<T> root) {
if (root != null) stack.push(root);
}
@Override
public boolean hasNext() {
while (!stack.isEmpty()) {
TreeNode<T> node = stack.peek();
if (node.children.isEmpty()) return true; // 找到叶子
stack.pop();
// 从右往左压入子节点,保证左子树先被访问
for (int i = node.children.size() - 1; i >= 0; i--) {
stack.push(node.children.get(i));
}
}
return false;
}
@Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return stack.pop().data; // 弹出并返回叶子节点数据
}}
配合 Iterable 使用更自然
让树节点类或树容器实现 Iterable<T>,返回你的 LeafIterator,就能直接用于 for-each:
- 在
TreeNode类中加方法:public Iterable<T> leaves() { return () -> new LeafIterator<>(this); } - 调用:
for (String leaf : root.leaves()) { ... }
注意边界与扩展性
实际使用时需考虑:
- 空树(
null根)应安全处理,hasNext()返回false - 若需 BFS 遍历叶子(按层序),把
Deque换成Queue(如LinkedList),用offer/poll替代push/pop - 如果树有父指针或支持二叉结构,可改用递归+内部状态机,但栈方式更通用、无栈溢出风险
不复杂但容易忽略:这个迭代器是**单次、不可重用**的——遍历完一次后,再次调用 hasNext() 总是 false。如需重复遍历,每次新建实例即可。

















