二叉树——二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

这是经典的二叉树层序遍历(BFS),用队列实现。

思路

  • 使用Queue保存每一层节点
  • 每次先获取当前队列大小,代表这一层右多少节点
  • 依次出队、收集值,再把左右孩子入队
  • 一层收集完,加入结果集合

Java完整代码实现如下:

import java.util.*;

class TreeNode {

int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}

class Solution {

public List<List> levelOrder(TreeNode root) {
List<List> res = new ArrayList<>();
if (root == null) return res;

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

while (!queue.isEmpty()) {
// 当前层的节点个数
int levelSize = queue.size();
List level = new ArrayList<>();

for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
level.add(node.val);

if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}

res.add(level);
}

return res;
}
}

复杂度:

  • 时间:O(n) 每个节点入队出队各一次
  • 空间:**O(n) **队列最多存一层节点(满二叉树最后一层约 n/2)

代码解释:

  • ArrayList:动态数组
  • LinkedList:双向链表
    它们都实现了List接口,用法几乎一样,但底层结构完全不同,性能天差地别

1.ArrayList(动态数组)

  • 底层是数组
  • 数组特点:连续内存、支持随机访问
  • 初始化右容量,满了会自动扩容(复制到新数组)

优点

  • 查找/访问极快:get(i) 时间复杂度 O(1)
  • 遍历速度快

缺点

  • 插入、删除慢:中间插入要移动后面所有元素
  • 扩容有开销

什么时候用?
读多写少、频繁查找、遍历
比如:存储列表数据、展示数据、层序遍历存结果

2.LinkedList(双向链表)

  • 底层是双向链表
  • 每个节点存:前节点、值、后节点
  • 内存不连续

优点

  • 插入、删除极快:只改指针,不用移动元素
  • 不需要扩容

缺点

  • 查找慢:要从头/尾遍历,get(i) 复杂度 O(n)
  • 占用内存更大(每个节点多存前后指针)

什么时候用?
频繁增删、尤其是头尾操作
比如:队列、栈、LRU缓存

回到代码中来
1.Queue queue = new LinkedList<>();
这里必须用LinkedList,因为:

  • Queue接口需要快速入队、出队(头尾操作)
  • ArrayList 做队列性能极差

2.List<List> res = new ArrayList<>();
存结果用动态数组,因为只添加、不删、最后要遍历输出,ArrayList 最快。

总结:

  • ArrayList = 数组:查得快,增删慢
  • LinkedList = 链表:增删快,查得慢

queue.offer(root)是什么?

  • offer:入队、添加到队列尾部
  • 意思:把根节点放进队列

为什么用 offer 而不是 add?
Queue 队列接口推荐用:

  • offer(e)添加元素,成功返回 true
  • poll():取出并删除队首元素
  • peek():看一眼队首但不删

它们比 add/remove 更安全,不会抛异常。

posted @ 2026-04-15 11:21  ZealousMclaren  阅读(21)  评论(0)    收藏  举报