在 Java 中,循环(遍历)树形结构通常有两种常见的方式:深度优先遍历(DFS, Depth-First Search)和广度优先遍历(BFS, Breadth-First Search)

树是一种递归结构,每个节点都有可能有多个子节点。常见的树节点结构如下:

class TreeNode {
    int value;
    List<TreeNode> children;

    public TreeNode(int value) {
        this.value = value;
        this.children = new ArrayList<>();
    }

    public void addChild(TreeNode child) {
        children.add(child);
    }
}

接下来分别介绍如何通过 DFS 和 BFS 来遍历这个树形结构。

1. 深度优先遍历(DFS)

递归方式

深度优先遍历可以使用递归来实现。对于每个节点,首先访问它本身,然后递归地访问它的每个子节点。

public void dfs(TreeNode node) {
    if (node == null) return;

    // 访问当前节点
    System.out.println(node.value);

    // 递归访问每个子节点
    for (TreeNode child : node.children) {
        dfs(child);
    }
}

示例:

假设有以下树形结构:

1
       / \
      2   3
     / \
    4   5

代码:

public static void main(String[] args) {
    TreeNode root = new TreeNode(1);
    TreeNode child1 = new TreeNode(2);
    TreeNode child2 = new TreeNode(3);
    root.addChild(child1);
    root.addChild(child2);
    child1.addChild(new TreeNode(4));
    child1.addChild(new TreeNode(5));

    dfs(root);  // 输出: 1 2 4 5 3
}

输出顺序是:1 2 4 5 3,这就是深度优先遍历的顺序。

非递归方式(使用栈)

除了递归,还可以使用显式的栈来实现 DFS 遍历。

public void dfsIterative(TreeNode root) {
    if (root == null) return;

    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);

    while (!stack.isEmpty()) {
        TreeNode current = stack.pop();
        System.out.println(current.value);

        // 将子节点逆序压入栈中,这样可以保持左到右的访问顺序
        List<TreeNode> children = current.children;
        for (int i = children.size() - 1; i >= 0; i--) {
            stack.push(children.get(i));
        }
    }
}

2. 广度优先遍历(BFS)

广度优先遍历可以使用队列来实现,依次访问每个节点,并将子节点加入队列。

public void bfs(TreeNode root) {
    if (root == null) return;

    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        TreeNode current = queue.poll();
        System.out.println(current.value);

        // 将子节点加入队列
        for (TreeNode child : current.children) {
            queue.add(child);
        }
    }
}

示例:

同样的树形结构:

1
       / \
      2   3
     / \
    4   5
public static void main(String[] args) {
    TreeNode root = new TreeNode(1);
    TreeNode child1 = new TreeNode(2);
    TreeNode child2 = new TreeNode(3);
    root.addChild(child1);
    root.addChild(child2);
    child1.addChild(new TreeNode(4));
    child1.addChild(new TreeNode(5));

    bfs(root);  // 输出: 1 2 3 4 5
}

输出顺序是:1 2 3 4 5,这是广度优先遍历的顺序。

总结

  • 深度优先遍历(DFS):可以使用递归或栈来实现,优先深入子节点,再处理兄弟节点。
  • 广度优先遍历(BFS):使用队列来实现,优先访问每层的所有节点,然后处理下一层。

根据不同的应用场景,选择不同的遍历方式,例如 DFS 更适合查找路径、求解递归问题,而 BFS 更适合寻找最短路径或分层处理树的结构。