二叉树(二)深度遍历和广度遍历

news/2024/9/22 13:16:02 标签: 算法, 数据结构

一、层序遍历

广度优先搜索:使用队列,先进先出

模板:

1、定义返回的result和用于辅助的队列

2、队列初始化:

root非空时进队

3、遍历整个队列:大循环while(!que.empty())

记录每层的size以及装每层结果的变量(记得每层循环结束后保存结果的值)

4、遍历每层:小循环for或while(size--)

出1进2:先记录当前即将出队的node

node出队,如果孩子节点非空即进队

  vector<vector<int>> levelOrder(TreeNode* root) {
       vector<vector<int>> result;
       //借助队列来实现
       queue<TreeNode*>que;//(先进先出,层序遍历)(保存节点指针,孩子信息才不丢失)
        
        if(root) //先弹进root
          que.push(root);

       while(!que.empty()){//队列不为空时,都要遍历;没有继续加入的,则说明快要遍历完了
          int size=que.size(); //保存当前层的大小
          vector<int> vec;//vec记录每层的节点元素,在循环内定义,不用每次清空

          //将总遍历切割成一层一层的
          while(size--){
            //对一层元素进行操作:出一个根节点(要先记录val),则进两个它的孩子节点(如果有)
             TreeNode*node=que.front();
             vec.push_back(node->val);

             que.pop();

             if(node->left)
               que.push(node->left);
             if(node->right)
               que.push(node->right);
          }

         result.push_back(vec);
       }
       
          return result;
    }

 变式:求层平均值

  vector<double> averageOfLevels(TreeNode* root) {
       vector<double> result;
       queue<TreeNode*> que;

       if(root!=NULL) 
         que.push(root);

        while(!que.empty()){
            int size=que.size();//当前层元素个数
            double sum=0;

            for(int i=0;i<size;i++){
                TreeNode* node=que.front(); //先保存
                sum+=node->val;

                que.pop();//再弹出

                if(node->left)//最后进两个
                  que.push(node->left);
                if(node->right)
                  que.push(node->right);
            }
            result.push_back(sum/size);
        }

       return result;
    }

 注意:最后要用到sum/size;所以不能用while(size--),因为size会改变,而要用for循环

同理,每层循环要记录size,就是因为que.size()也会改变

二、深度遍历(前中后序,递归)

深度优先搜索:使用栈,先进后出

模板:

前序:

   void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 根
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }

中序:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    vec.push_back(cur->val);    // 根
    traversal(cur->right, vec); // 右
}

后序:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    traversal(cur->right, vec); // 右
    vec.push_back(cur->val);    // 根
}

三、对比

1、获取最大深度

 深度优先(前序):

   int getdepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftdepth = getdepth(node->left);       // 左
        int rightdepth = getdepth(node->right);     // 右
        int depth = 1 + max(leftdepth, rightdepth); // 中
        return depth;
    }

广度优先:

int maxDepth(TreeNode* root) {
        //1、定义结果变量和辅助队列
     int depth=0;
     queue<TreeNode*> que;
        
        //2、队列初始化
     if(root)
      que.push(root);
        
        //3、大循环并记录每层的size
     while(!que.empty()){
        int size=que.size();
         
         //4、小循环:遍历一层,存1出1进2
        while(size--){
          TreeNode*node=que.front();
          
          que.pop();

          if(node->left)
           que.push(node->left);
          if(node->right)
           que.push(node->right);
        }
        depth++;
     }
     return depth;
    }

2、获取最小深度 

深度优先(前序):

    int minDepth(TreeNode* root) {
      if(root==NULL)
       return 0;
      
      int lh=minDepth(root->left);
      int rh=minDepth(root->right);
      if(!root->left&&root->right)
       return 1+rh;
      if(root->left&&!root->right)
       return 1+lh;
      return 1+min(lh,rh);
    }

考虑仅有一个孩子节点时,返回的应是1+子树的最小深度 

广度优先:

 int minDepth(TreeNode* root) {
        //1、定义结果变量和辅助队列
     int depth=0;
     queue<TreeNode*> que;
        
        //2、队列初始化
     if(root)
      que.push(root);
        
        //3、大循环并记录每层的size
     while(!que.empty()){
        int size=que.size();
         
         //4、小循环:遍历一层,存1出1进2
        while(size--){
          TreeNode*node=que.front();
          
          que.pop();

          if(node->left)
           que.push(node->left);
          if(node->right)
           que.push(node->right);

           //如果遇到叶子节点了,说明可以完成最小深度计算了
           if(!node->left&&!node->right)
             return depth+1;//注意是+1(逻辑上要遍历完一层才+1,这里提前结束就提前加)
        }
        depth++;
     }
     return depth;
    }

考虑遇到叶子节点时,就可以返回最小深度了


http://www.niftyadmin.cn/n/5670327.html

相关文章

《论分布式存储系统架构设计》写作框架,软考高级系统架构设计师

论文真题 分布式存储系统&#xff08;Distributed Storage System&#xff09;通常将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据&#xff0c;存储服务器成为系统性能的瓶颈&#xff0c;也是可靠性和安全性的焦点&#xff0c;不能满…

Cisco 基础网络汇总

⭕个人主页 可惜已不在 ⭕可以分享给身边有需要的人 ⭕有用的话就留下一个三连吧 目录 前言: 一.网络及网络设备认识 二. 二层网络 三. 生成树、端口 四. 三层网络 五.访问控制 六.NAT 七.DHCP 八.PPP 九.帧中继 十.热备份 十一.综合实验 十二.WLAN 十三.Cisco P…

Vue3与Flask后端Demo

文章目录 准备工作Flask 后端设置Vue3 前端设置跨域问题测试 准备工作 安装开发环境 安装 Python&#xff08;推荐 Python 3.8 或更高版本&#xff09;。安装 Node.js&#xff08;推荐 LTS 版本&#xff09;。安装 PyCharm&#xff08;用于 Flask 开发&#xff09;和 VSCode&am…

计算机网络(八) —— Udp协议

目录 一&#xff0c;再谈端口号 1.1 端口号 1.2 netsta命令 二&#xff0c;UDP协议 2.1 关于UDP 2.2 Udp协议格式 2.3 Udp协议特点 2.4 Udp的缓冲区 一&#xff0c;再谈端口号 http协议本质是“请求 - 响应”形式的协议&#xff0c;但是应用层需要先将数据交给传输层&…

【笔记】第三节 组织与性能

3.1 基本成分 3.2 微观组织特征 0.6-0.8C%碳素钢的组织为珠光体和少量的铁素体。 如何把组织和性能联系起来&#xff1f;德国克虏伯公司的研究——珠光体片间距与渗碳体片层厚度成比例&#xff1a; t s 0 ( ρ 15 ( C % ) − 1 ) ts_0(\frac{\rho}{15(C\%)}-1) ts0​(15(C%)…

Flyway 数据库差异处理

Flyway 数据库差异处理详解 在软件开发过程中&#xff0c;数据库 schema 的变更是不可避免的&#xff0c;尤其是在多人协作、多环境部署时&#xff0c;不同环境中的数据库结构可能出现差异。Flyway 作为一个数据库迁移工具&#xff0c;通过版本控制和自动化迁移&#xff0c;确…

力扣最热一百题——搜索二维矩阵

目录 题目链接&#xff1a;240. 搜索二维矩阵 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;暴力不解释 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运行时间 时间复杂度以及空间复杂度 解法二&#xff1a;利用自带的大小关系进行Z型走…

【计算机网络】理解应用层协议HTTP

目录 HTTP协议认识URLHTTP协议的请求如果我们想获得请求报文的完整内容&#xff0c;怎么办&#xff1f; HTTP协议的响应HTTP的方法GETvsPOST HTTP的状态码HTTP常见HeaderHTTP版本实现一个简单的HTTP服务器 HTTP协议 HTTP协议是一种超文本传输协议&#xff0c;它定义了客户端与…