层序遍历?看这一篇就够了!

68 篇文章 1 订阅
订阅专栏

点关注不迷路

1.树的层序遍历

顾名思义,对于树型结构,层序遍历就是按层从上到下,每层按一定顺序对树的节点进行遍历。我们通过如图所示的二叉树进行说明:对于左边的二叉树,按层划分后可得到右边的分层结构。

如果按照每层从左到右的遍历逻辑,这棵二叉树的层序遍历序列就是 [ 1 , 4 , 2 , 7 , 20 , 5 ] [1, 4, 2, 7, 20, 5] [1,4,2,7,20,5]。通过代码如何实现呢?一般地,我们利用队列 q u e u e queue queue 作为容器,按照如下逻辑进行遍历:

// 0. 声明队列
queue<TreeNode*> q;
// 1. 将根节点加入队列
q.push(root);
// 2. 遍历队列中每个节点
while(!q.empty()) {
    TreeNode* cur = q.front();
    q.pop();
    // 3. 记录当前节点值
    vec.push(cur->val);
    // 4. 将左右孩子放入队列
    q.push(cur->left);
    q.push(cur->right);
}

同一层中的节点自左向右遍历是通过队列实现的:还是拿之前的例子来说,先将值为 1 1 1 的节点放入队列,然后将先左孩子 4 4 4 放入队列,再将右孩子 2 2 2 放入队列,由于队列是先进先出型结构,所以保证了值为 4 4 4 的节点要先于值为 2 2 2 的孩子处理;同样地,第三层节点放入队列的顺序依次为 7 , 20 , 5 7, 20, 5 7,20,5,与之后的处理顺序相同,保证了从左向右的顺序。过程如下图所示:(黄色代表加入队列的节点、粉色代表当前处理的节点、蓝色表示吃瓜的节点)

1

2

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一般地,在遍历完第 k k k 层的最后一个节点后,该层所有节点都被弹出了队列,且其孩子节点(均处于 k + 1 k + 1 k+1 层)都被存入了队列且未处理,所以当前队列的长度就是 k + 1 k + 1 k+1 层的节点数量。

所以,通过提前记录队列长度,可以方便地应对一些需要对各层进行特殊处理的问题。

特别地,为了防止二叉树为空、遍历到叶节点等情况,需要加入一些特判元素。修改后的模板如下:

// 1.初始化
queue<TreeNode*> q;
if(root == NULL) { // 二叉树为空
    return;
}
q.push(root);

// 2.遍历整棵树
while(1) {
    int cnt = q.size(); // 要处理层的节点个数
    if(cnt == 0) break; // 已经遍历完二叉树
    
    // 3.遍历该层
    while(cnt--) {
        TreeNode* cur = q.front();
        q.pop();
        
        // 4.对 cur 的操作,根据题意更改
        action(cur);
        
        // 5.将左右孩子放入队列
        if(cur->left) q.push(cur->left);
        if(cur->right) q.push(cur->right);
    }
}

点关注不迷路

2.几道例题

说明:对于不同的题目,只需要在我们的模板基础上增加或更改一些元素,所以对于下面的每道例题,我们在代码中只重点注释修改的部分。

第一题:二叉树的层序遍历

我们先从基础的力扣102题来入手:题目要求返回一个二维容器,其中的每一个容器记录着某一层的所有节点值。我们只需要层序遍历二叉树,并按层遍历节点,将其加入 v e c t o r vector vector。在遍历完该层后,将记录了该层所有节点的 v e c t o r vector vector 加入结果容器即可,代码如下:

  vector<vector<int>> levelOrder(TreeNode* root) {
      // 声明结果二维容器
      vector<vector<int>> result;
      queue<TreeNode*> q;
      if(root == NULL) return result;
      q.push(root);
      while(1) {
          int cnt = q.size();
          if(cnt == 0) break;
          // 记录该层节点的容器
  		vector<int> v;
          while(cnt--) {
              TreeNode* cur = q.front();
              q.pop();
              // 将当前节点存入容器
  			v.push_back(cur->val);
              if(cur->left) q.push(cur->left);
              if(cur->right) q.push(cur->right);
          }
          // 处理完该层,加入结果容器
          result.push_back(v);
      }
      return result;
  }

第二题:二叉树的层序遍历 II

与上一道题不同,要求从下到上遍历。实际上我们只需要从上向下遍历后,将结果容器翻转即可。C++的标准库STL给我们提供了容器翻转的函数:
r e v e r s e ( r e s u l t . b e g i n ( ) , r e s u l t . e n d ( ) ) reverse(result.begin(), result.end()) reverse(result.begin(),result.end())

第三题:二叉树的锯齿形层序遍历

与前两题不同,对于给定的如图所示的树,锯齿形遍历需要偶数层从右向左返回结果,奇数层从左向右返回结果,也即返回的结果序列应为:

[
  [3],
  [20,9],
  [15,7]
]

本质上,我们只需要翻转偶数层的容器,就可以把从左向右的遍历转化为从右向左的遍历。在代码实现时,我们增加一个布尔型变量,记录当前层是否需要翻转,并每层将该变量取反即可:

vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
    vector<vector<int>> result;
    // 当前层是否需要翻转
    bool flag = false;
    queue<TreeNode*> q;
    if(root == NULL) return result;
    q.push(root);
    while(1) {
        int cnt = q.size();
        if(cnt == 0) break;
        vector<int> v;
        while(cnt--) {
            TreeNode* cur = q.front();
            q.pop();
            v.push_back(cur->val);
            if(cur->left) q.push(cur->left);
            if(cur->right) q.push(cur->right);
        }
        // 判断是否翻转
        if(flag) reverse(v.begin(), v.end());
        result.push_back(v);
        // 取反
        flag = !flag;
    }
    return result;
}

第四题:二叉树的最大深度

这是力扣第104题,在我们的模板里,每处理完一层,才退出内层循环,并开始新一轮外层循环。而本题要找最大深度,就是找一共处理了多少层,所以提前维护一个记录层数的变量 d e p t h depth depth,然后在外层循环内每次增加该变量即可:

int maxDepth(TreeNode* root) {
    int depth = 0; // 声明深度
    queue<TreeNode*> q;
    if(root == NULL) return 0;
    q.push(root);
    while(1) {
        int cnt = q.size();
        if(cnt == 0) break;
        depth++; // 处理新一层前深度自加
        while(cnt--) {
            TreeNode* cur = q.front();
            q.pop();
            if(cur->left) q.push(cur->left);
            if(cur->right) q.push(cur->right);
        }
    }
    return depth;
}

特别地, d e p t h + + depth++ depth++ 语句必须要放在判断 c n t = 0 cnt = 0 cnt=0 的语句之后,否则若遍历到最后一层,深度自加之后才会退出循环,导致结果错误。

第五题:二叉树的最小深度

第111题要求“最小深度”(找到离根节点最近的叶子节点),由于我们进行的是层序遍历,只要找到一个叶子节点,该节点就一定是所求的最近节点。所以,遍历过程中增加判断叶子节点的部分即可。来看看代码:

int minDepth(TreeNode* root) {
    int depth = 0;
    queue<TreeNode*> q;
    if(root == NULL) return 0;
    q.push(root);
    while(1) {
        int cnt = q.size();
        if(cnt == 0) break;
        depth++;
        while(cnt--) {
            TreeNode* cur = q.front();
            q.pop();
            // 叶子节点
            if(!cur->left && !cur->right) return depth;
            if(cur->left) q.push(cur->left);
            if(cur->right) q.push(cur->right);
        }
    }
    return depth;
}

最后总结

层序遍历的关键,要明确每一轮循环的具体过程。二叉树遍历相关的算法题,都是基于层序遍历框架的,我们只要搞清楚 r o o t root root 节点本身要做什么,根据题目要求进行处理,再把左右孩子往队列里一放就行了。

如果本文讲的层序遍历对你有一些启发,请三连支持作者~~~

推荐阅读

点关注不迷路

【数据结构】二叉树的层序遍历(BFS)
Colorful___的博客
10-06 9437
层序遍历是一种广度优先搜索的遍历方式,适用于树结构。通过利用队列实现层序遍历,我们可以按照从上到下、从左到右的顺序逐层遍历树中的节点。层序遍历广泛应用于树的分析、最短路径寻找、二叉树的构建等场景。掌握层序遍历的原理和实现方法将对解决相关问题非常有帮助。
层序遍历
Sunye_bunny的博客
04-17 1046
层序遍历 设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层. 上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历 例题: 给出一颗二叉树的后序遍历序列和中序遍历序列,求这颗二叉树的层序遍历序列。 (输入样例和输出样例如运行结果所示) #include<cstdio> #i...
数据结构与算法学习day18-层序遍历
最新发布
weixin_48990728的博客
08-28 468
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现,
二叉树及n叉树的层序遍历,看这一篇就够
神仙菜ccc的博客
04-18 1032
关于Leetcode上二叉树及n叉树的层序遍历 层序遍历二叉树,顾名思义,就是从左到右一层一层的去遍历二叉树。 通常需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。 而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。 下面上题目: 题面及样例输入输出: 题目来源:leetcode(力扣) 题目链接:https://leetcode-cn.com/problems/binary-tree-level-orde
树的知识小结(期末复习看这一篇就够啦!)
sara_shengxin的博客
06-12 1065
树:T={D,R},D是包含n个节点的有穷集合,R代表关系。有且仅有一个节点d0D,则此时R没有前驱节点,即d0为根节点出节点d0外,D中每个节点对于R有且一个前驱节点D中每个节点对于R可以有零个或多个后继节点一个空树(或空的树节点)是一个树一个由根节点和若干个子树(可能是空树)组成的集合是一个树。其中每个子树本身也是树给定N个权值作为N个叶子结点构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。
c++实现简单二叉树?这篇就够了!
私が悪いのではなく、この世界が悪いのです
11-17 498
二叉树一些概念创建&初始化二叉树二叉树的三种遍历递归版非递归版 一些概念 满二叉树:所有的分支节点都存在左子树和右子树,所有的叶子都在最下面一层。 完全二叉树:叶子节点只能出现在最下层和次最下层,且最下层的叶子节点集中在树的左部。 创建&初始化二叉树 typedef int datatype; typedef struct bitnode{ datatype data; struct bitnode *lchild,*rchild; }BiTNode,*BiTree;
数据结构——二叉树的原理与代码应用
流楚丶格念的博客
10-30 4608
本文下月再整理 这月凑够40篇
华为OD-华为机试精讲500篇系列文章目录介绍(持续补充ing)
qq_36130719的博客
01-29 1726
华为OD?华为OD是一种新的用工方式,其全称为Outsourcing Dispatch(外包派遣)。这种方式是由华为与外部的人力资源服务公司如外企德科或科锐国际合作进行招聘。OD模式下,员工的劳动合同并非直接与华为签订,而是在这些第三方人力资源服务公司的名义下。这意味着OD员工的工作归属感可能不如传统华为员工强烈,但他们在薪酬待遇上通常会有所保障。华为OD主要面向的是13级至17级的软件开发类岗位,包括但不限于前端开发、后端开发、软件测试、算法、大数据等领域。
树的层序遍历
zmm0628的博客
05-11 1919
树的层序遍历 树的先序,中序,后序遍历对应了深度优先遍历。而层序遍历为广度优先遍历。 层序遍历很好理解,从根节开始一层层的遍历访问,访问完第一层访问第二层。 定义一个队列就可以搞定层序遍历了。 还是这个例子,这个树的层序遍历序列为:1 2 3 4 5 6 代码实现 //层序遍历 void LevelOrder(LinkQueue Q,BiTree T){ BiTree p; EnQueue(Q,T);//将根节点入队 while(!isEmptyQueue(Q)){//队列不空,循环 DeQu
序列化(层序遍历
GoJawee的博客
09-16 913
使用层序遍历去遍历每一个节点, 当该结点为NULL时,str = str+"#!" 当该结点非NULL时,str = str+该节点的data+"!" #include <iostream> #include <vector> #include<queue> #include <string> using namespace std;typedef struct TreeNode { str
七、二叉树(5):二叉树的层序遍历
努力努力努力
09-11 5976
学会二叉树的层序遍历,可以一口气打完以下十题: 102.二叉树的层序遍历 107.二叉树的层次遍历II 199.二叉树的右视图 637.二叉树的层平均值 429.N叉树的前序遍历 515.在每个树行中找最大值 116.填充每个节点的下一个右侧节点指针 117.填充每个节点的下一个右侧节点指针II 104.二叉树的最大深度 111.二叉树的最小深度 在之前写过这篇文章二叉树:层序遍历登场!(opens new window),可惜当时只打了5个,还不够,再给我一次机会,我打十个! ...
如何实现二叉树的层序遍历
10-14
二叉树的层序遍历可以使用队列来实现。具体步骤如下: 1. 将根节点入队。 2. 当队列不为空时,依次取出队首元素,将其值存入结果列表中,并将其左右子节点(如果存在)入队。 3. 重复步骤2,直到队列为空。 以下是Python代码实现: ```python def levelOrder(root): if not root: return [] queue = [root] res = [] while queue: node = queue.pop(0) res.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) return res ```
写文章

热门文章

  • 层序遍历?看这一篇就够了! 18459
  • 字节跳动客户端一轮面试(附带答案版~~~) 4314
  • LeetCode 第 222 场周赛 题解 2877
  • 字节跳动客户端三面面经(带答案!!!) 1590
  • 字节跳动客户端二轮面试(附带答案版~~~) 1586

分类专栏

  • 面经 4篇
  • 各类bug
  • 二分法 13篇
  • LC周赛 10篇
  • Leetcode 68篇
  • 计网&操作系统
  • Atcoder 1篇
  • DFS_BFS 7篇
  • 双指针_滑动窗口 30篇
  • CF 20篇

最新评论

  • 牛客巅峰赛第7场-牛牛的独特子序列

    格林小镇: 大佬,方法二中bool函数中的作用还是不太懂,为什么满足这个就要改变左边界,谢谢 class Solution { public: bool check(int mid, string s) { int n = s.size(); int a = 0, b = 0, c = 0; for(int i = 0; i < n; i++) { if(a < mid) a += (s[i] == 'a'); else if(b < mid) b += (s[i] == 'b'); else c += (s[i] == 'c'); } return c >= mid; } int Maximumlength(string s) { int n = s.size(); int l = 0, r = n, ans = 0; while(l <= r) { int mid = l + r >> 1; if(check(mid, s)) { ans = mid; l = mid + 1; } else { r = mid - 1; } } return ans * 3; } };

  • 层序遍历?看这一篇就够了!

    qq_53158952: 明白层序遍历了谢谢

大家在看

  • 磁珠的工作原理:【图文讲解】
  • 力扣 88.合并两个有序数组 121.买卖股票的最佳时机 642
  • Claude全面升级,我们试了一下,确实碾压OpenAI o1
  • Springboot计算机毕业设计大学生体质测试管理系统415ef
  • 免费SSL证书和付费证书的区别是什么?

最新文章

  • AtCoder Beginner Contest 190 题解(A-D)
  • 字节跳动客户端一面面经(附答案)
  • 字节跳动客户端三面面经(带答案!!!)
2021年7篇
2020年98篇

目录

目录

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家河北城市玻璃钢雕塑全国发货蓬江玻璃钢雕塑山西学校玻璃钢美陈雕塑双阳玻璃钢雕塑厂家玻璃钢雕塑是怎么做的泡沫雕塑玻璃钢商场楼体美陈玻璃钢仿铜雕塑做旧处理上海定制玻璃钢雕塑销售电话定做玻璃钢雕塑厂家无锡玻璃钢仿铜雕塑定做玫瑰花玻璃钢雕塑玻璃钢冰雪雕塑商场美陈制作品牌湖南人像雕塑玻璃钢青岛玻璃钢大象雕塑玻璃钢雕塑主要材料玻璃钢花盆造型图片承德景观玻璃钢雕塑制作户外发光玻璃钢雕塑制作玻璃钢狗雕塑摆件南岸玻璃钢雕塑南平模压法玻璃钢雕塑报价武汉创意玻璃钢雕塑订做价格金山玻璃钢雕塑性价比高息烽玻璃钢雕塑厂哪家好泰安玻璃钢卡通座椅雕塑户外玻璃钢卡通雕塑报价表温州玻璃钢卡通雕塑厂家报价山西玻璃钢假山雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化