数据结构二叉树——层序遍历 扩展二叉树的左视图
二叉树的层序遍历
层序遍历的特点是:从上到下、从左到右依次访问每一层的所有节点,就像 “按楼层逐层扫描”。例如,对于这样一棵二叉树:
层序遍历的结果是 [[3], [9, 20], [15, 7]](每一层的节点值组成一个子列表)。
实现的关键是利用队列的 “先进先出(FIFO)” 特性:
- 先访问的节点,其左右孩子也会按顺序先被访问,恰好符合层序遍历的 “从左到右” 规则。
- 每次处理完一层的所有节点后,队列中剩余的节点恰好是下一层的所有节点。
地址:https://leetcode.cn/problems/binary-tree-level-order-traversal/description/
核心是用 队列(FIFO 先进先出特性)实现二叉树的层序遍历
本质是 “按楼层逐层扫描节点”
把每一层的节点值整理成列表
1.初始化准备
- 创建一个外层列表 list,用于存储最终的层序遍历结果(每个元素是一层的节点值列表)。
- 特殊情况处理:如果根节点 root 为 null(空树),直接返回空列表。
- 创建一个队列 queue(用 LinkedList 实现),用于存储待访问的节点,初始时将根节点入队。
2.逐层遍历节点
使用 while 循环持续处理队列中的节点,直到队列为空(所有节点都访问完毕)
3. 处理当前层的所有节点
- 创建当前层的列表:List list2 用于存储当前层所有节点的值。
- 记录当前层的节点数量:int size = queue.size(),这个 size
就是当前层的节点总数(必须先记录,因为后续队列会加入下一层的节点,大小会变化)。 - 循环处理当前层的每个节点:用 for 或 while 循环执行 size 次,每次取出队列的头节点
while (size != 0) {TreeNode cur = queue.poll(); // 取出队首节点(当前层的一个节点)list2.add(cur.val); // 将当前节点的值加入当前层列表...size--;
}
4. 把下一层的节点入队
对于当前节点 cur,如果它有左孩子或右孩子,就将它们依次加入队列(保证下一层的节点按 “从左到右” 的顺序等待访问)
if (cur.left != null) {queue.offer(cur.left); // 左孩子入队
}
if (cur.right != null) {queue.offer(cur.right); // 右孩子入队
}
5. 收集当前层结果
当前层的所有节点处理完毕后,list2 中已经存储了当前层的所有节点值,将其加入外层列表 list
list.add(list2);
6. 循环结束,返回结果
当队列空了(queue.isEmpty() 为 true),说明所有层都已处理完毕,返回外层列表 list 即可。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;/*** Definition for a binary tree node.* public 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<Integer>> levelOrder(TreeNode root) {// 创建双层的顺序表,存储最终结果的列表List<List<Integer>> list = new ArrayList<>();if (root == null) {return list;}// 创建队列,注意需要存储TreeNode类型Queue<TreeNode> queue = new LinkedList<>();queue.offer(root); // 队列不为空时循环(处理每一层)while (!queue.isEmpty()) {// 存储当前层的节点值List<Integer> list2 = new ArrayList<>();// 当前层的节点数量(必须先记录,因为队列大小会动态变化)int size = queue.size();// 循环处理当前层的所有节点while (size != 0) {// 取出队首节点TreeNode cur = queue.poll(); // 把当前节点的值加入当前层列表list2.add(cur.val); // 左孩子非空则入队if (cur.left != null) {queue.offer(cur.left);}// 右孩子非空则入队if (cur.right != null) {queue.offer(cur.right);}
// 处理完一个节点,当前层剩余数量减1size--; }list.add(list2);}return list;}
}
扩展题
二叉树的左右视图
左右视图的核心是获取每一层的 “第一个节点”(左视图)或 “最后一个节点”(右视图),可通过层序遍历实现:
按层遍历二叉树(同层序遍历逻辑)。
对每一层的节点,仅记录 “第一个节点”(左视图)或 “最后一个节点”(右视图)。
相信大家比上面那个自己动手敲了出来,这个很快的就想到怎么做出来
无非就是把每一个第一个或者最后一个重新存储起来
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;/*** Definition for a binary tree node.* public 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<Integer> leftView(TreeNode root) {// 存储左视图结果(每一层的第一个节点)List<Integer> result = new ArrayList<>();if (root == null) {return result;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);// 队列不为空时,逐层处理(复用层序遍历的外层循环)while (!queue.isEmpty()) {// 当前层的节点数量(必须先记录,队列大小会动态变化)int size = queue.size();// 循环处理当前层的所有节点(复用层序遍历的内层循环)for (int i = 0; i < size; i++) {TreeNode cur = queue.poll();// 核心逻辑:只记录当前层的第一个节点(i=0时)这就是左视图if (i == 0) {result.add(cur.val);}// 左孩子先入队(保证下一层节点从左到右顺序,复用层序遍历的入队逻辑)if (cur.left != null) {queue.offer(cur.left);}// 右孩子后入队if (cur.right != null) {queue.offer(cur.right);}}}return result;}
}