当前位置: 首页 > news >正文

c++之二叉树

1、二叉树的递归

递归三要素

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) //确定递归函数的参数和返回值
   {
        if (cur == NULL) return;      //   终止条件
       
     
        vec.push_back(cur->val);    // 中       单层递归逻辑
        traversal(cur->left, vec);  // 左       单层递归逻辑
        traversal(cur->right, vec); // 右       单层递归逻辑
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

深度前序遍历的过程

2、 二叉树的遍历方式

1、深度优先

先往深走,遇到叶子节点再往回走

前序遍历(递归法,迭代法)

中序遍历(递归法、迭代法)

后序遍历(递归法、迭代法)

递归法

前序遍历  (根、左、右)

class Solution{

public:
    void traversal(TreeNode* cur vector<int>& vec)
    {
         if(cur == NULL) return;   //终止条件
         
         //单层逻辑
         vec.push_back(cur ->val);//根
         traversal(cur ->left,vec);//左
         traversal(cur ->right,vec);//右
          
       
    }
   vector<int> preorderTraversal(TreeNode* root)
      {
        vector<int> result;
        traversal(root,result);//将树传入生成数组
        return result;
      }


}

中序遍历  (左、根、右)

class Solution{

public:
    void traversal(TreeNode* cur vector<int>& vec)
    {
         if(cur == NULL) return;   //终止条件
         
         //单层逻辑
         traversal(cur->left,vec);//左
         vec.push_back(cur ->val);//根
         traversal(cur->right,vec);//右
          
       
    }
   vector<int> preorderTraversal(TreeNode* root)
      {
        vector<int> result;
        traversal(root,result);//将树传入生成数组
        return result;
      }


}

后序遍历(左、右、根)

class Solution{

public:
    void traversal(TreeNode* cur vector<int>& vec)
    {
         if(cur == NULL) return;   //终止条件
         
         //单层逻辑
         traversal(cur->left,vec);//左
         traversal(cur->right,vec);//右
         vec.push_back(cur ->val);//根
         
          
       
    }
   vector<int> preorderTraversal(TreeNode* root)
      {
        vector<int> result;
        traversal(root,result);//将树传入生成数组
        return result;
      }


}

迭代法

使用栈的方式实现

中序遍历 (中、右、左)

class Solution{

public:
   vector<int> inorderTraversal(TreeNode* root){
      vector<int> result; //存放
      stack<TreeNode*>st;//创建一个栈
      if(root != NULL) st.push(root)//根节点
      while(!st.empty())//栈不为空
     {
     
        TreeNode* node = st.top();//指针指向栈顶部

        if(node != NULL)//顶部不是空节点
        {
          st.pop();//将该节点弹出,避免重复操作,下面将右、中、左节点加入栈中
          if(node ->right) st.push(node ->right);//添加右节点入栈(空节点不如栈)

          st.push(node);    // 添加根节点入栈
          st.push(NULL)    //中节点访问过,但是还没有处理,加入空节点为标记

          if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)

         

        }else{  //只有遇到空节点的时候,才将下一个节点放进结果集
            
              st.pop();  //将空节点弹出
              node = st.top();  //重新取出栈中元素
              st.pop();//弹出我们要记录的元素
              result.push_back(node->val);  //加入到容器中

          
           }
         
     }

    return result;
     
    }


}

2、广度优先遍历

一层一层的遍历

层次遍历(迭代法)

遍历顺序 : 根、左、右

 

分层 A / B G // C D H //E F

队列:先进先出

我们先把遍历每一层的元素先放到队列里面,然后放了之后就要开始准备下一次层的遍历。

弹出的时候存放它的子节点到队列中(这样的话就衔接上了,每一层元素都遍历了)

size记录每一层的节点数

个人理解:

极限一换一,顶罪,你爹出去了,儿子就得去队列里面顶罪

class Solution
{
public:
    vector<int> bfs(TreeNode *root)//返回的是一个int的vector
    {
        vector<int>res;
        queue<TreeNode *>q;//辅助队列
 
        if(root==NULL)return res;//小事件结束标志
        q.push(root);
 
        while(!q.empty())
        {
            res.push_back(q.front()->val);
            if(q.front()->left!=NULL)
            {
                q.push(q.front()->left);
            }
            if(q.front()->right!=NULL)
            {
                q.push(q.front()->right);
            }
            q.pop();//弹出第一个元素
        }
        return res;//只有最后才会执行这个
    }
};

代码随想录:


​class Solution{
       
public:
    vector<vector<int>> levelOrder(TreeNode* root){
      queue<TreeNode*> que;
       
      if(root != NULL) que.push(root);//节点存在,入队
      vector<vector<int>> result;//存放出队的数据
      while(!que.empty())//当队列不为空
        {
           int size = que.size();//记下队列元素个数
           vector<int> vec;
           for(int i = 0; i < size(); i++)
              {
                 TreeNode* node = que.front();//指针指向出口
                 que.pop();//出队
                 vec.push_back(node->val);//将出队元素插入容器
                 if(node ->left)  que.push(node -> left);//左儿子存在就进队
                 if(node ->right)  que.push(node ->right);//右儿子存在,就进队
                 
              }
              result.push_back(vec);
         
        }
            return  result;//返回容器

    }    
 
};

相关文章:

  • 字符串训练赛
  • Android性能优化之【启动优化】
  • Java 集合与数据结构 · 接口 interfaces ·Collection 常用方法 · Map 常用方法
  • 面试面不过?大厂面试官是这样说的···
  • 秒懂YUV444/YUV422/YUV420计算(二十九)
  • 模方重大更新,支持3ds max、新版大疆数据、匀色、多原点数据等
  • 论文教程之 138位科研工作者分享如何(认真地)阅读一篇科学论文
  • MVC、MVP、MVVM三种模式的介绍及区别
  • 注意力机制综述学习记录
  • 数据结构c语言版第二版(严蔚敏)第三章笔记
  • 羊了个羊,但是Python简(li)单(pu)版
  • 【软件测试】测试用例的设计方法
  • 二叉树的遍历问题
  • FPGA/HDL 人员开发利器-TerosHDL(开源 IDE)
  • 《谁动了我的奶酪》阅读笔记
  • 《Java编程思想》读书笔记-对象导论
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • eclipse的离线汉化
  • Fundebug计费标准解释:事件数是如何定义的?
  • httpie使用详解
  • Java比较器对数组,集合排序
  • java中具有继承关系的类及其对象初始化顺序
  • Python 反序列化安全问题(二)
  • Sass Day-01
  • uva 10370 Above Average
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 对象引论
  • 飞驰在Mesos的涡轮引擎上
  • 讲清楚之javascript作用域
  • 坑!为什么View.startAnimation不起作用?
  • 免费小说阅读小程序
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 责任链模式的两种实现
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 容器镜像
  • # Java NIO(一)FileChannel
  • #{} 和 ${}区别
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #Linux(Source Insight安装及工程建立)
  • (09)Hive——CTE 公共表达式
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转载)Linux 多线程条件变量同步
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET MVC第三章、三种传值方式
  • .NET连接数据库方式
  • .NET中两种OCR方式对比