2024.3.25-26记:二叉树的遍历

  • 二叉树的遍历
    • 深度优先遍历(DFS)
      • 递归遍历
        • 前序递归遍历:
        • 中序递归遍历
        • 后续递归遍历
      • 非递归遍历
        • 前序非递归遍历
        • 中序非递归遍历
        • 后续非递归遍历
    • 宽度优先遍历(BFS):

二叉树的遍历

二叉树遍历大体上分为深度优先遍历(DFS)和宽度优先遍历(BFS):

深度优先遍历(DFS)

对于深度优先遍历,又可以分为前序、中序和后序遍历,对于一个二叉树,无非包括三个部分根节点、左子树和右子树,其子树也是相同组成方式。顾名思义,二叉树的前中后序遍历就是表示什么时候遍历该二叉树的根节点(包括其子树),例如对于前序遍历而言,我们先遍历根节点然后在遍历左子树,最后再遍历右子树。各个遍历方式如下所示:

前序遍历次序:–>左子树–>右子树
中序遍历次序:左子树–>–>右子树
后续遍历次序:左子树–>右子树–>

对于如下所示的树:
在这里插入图片描述

前序遍历:1,2,4,5,3,6
中序遍历:4,2,5,1,3,6
后续遍历:4,5,2,6,3,1

可以验证上述理论,对于子树也相同适用。

递归遍历

如何实现上述遍历呢,我们很容易想到递归方式,例如对于前序遍历,我们先遍历根节点,然后分别递归遍历左子树右子树。代码实现也很简单:

// 前序遍历就是在递归前处理根节点数据,这里打印数据
std::cout << root->val << std::endl;
preorderTraversal(root->left);
preorderTraversal(root->right);

同样的对于中序和后序:

inorderTraversal(root->left);
// 中序遍历就是在递归中间处理根节点数据,这里打印数据
std::cout << root->val << std::endl;
inorderTraversal(root->right);
postorderTraversal(root->left);
postorderTraversal(root->right);
// 后序遍历就是在递归后处理根节点数据,这里打印数据
std::cout << root->val << std::endl;

具体代码如下:

前序递归遍历:
class Solution {vector<int> preorderTraversal(TreeNode *root) {vector<int> res;preorderTraversal(root, res);return res;}void preorderTraversal(TreeNode *root, vector<int> &res) {if (!root) {return;}res.push_back(root->val);preorderTraversal(root->left, res);preorderTraversal(root->right, res);}
};
中序递归遍历
class Solution {public:vector<int> inorderTraversal(TreeNode *root) {vector<int> res;inorderTraversal(root, res);return res;}void inorderTraversal(TreeNode *root, vector<int> &res) {if (!root) {return;}inorderTraversal(root->left, res);res.push_back(root->val);inorderTraversal(root->right, res);}
};
后续递归遍历
class Solution {public:vector<int> postorderTraversal(TreeNode *root) {vector<int> res;postorderTraversal(root, res);return res;}void postorderTraversal(TreeNode *root, vector<int> &res) {if (!root) {return;}postorderTraversal(root->left, res);postorderTraversal(root->right, res);res.push_back(root->val);}
};

非递归遍历

对于非递归遍历,我们可以从递归展开中获得灵感,对于递归,如果没有到底部,之前的所有数据会一直执行压栈,只是在压栈过程中何时遍历根节点的问题。直接看代码:

前序非递归遍历
class Solution {public:vector<int> preorderTraversal(TreeNode *root) {vector<int> res;stack<TreeNode *> q;while (!q.empty() || root) {if (root) {// 在压栈前遍历根节点res.push_back(root->val);q.push(root);root = root->left;} else {root = q.top();q.pop();root = root->right;}}return res;}
};
中序非递归遍历
class Solution {public:vector<int> inorderTraversal(TreeNode *root) {vector<int> res;stack<TreeNode *> q;while (!q.empty() || root) {if (root) {q.push(root);root = root->left;} else {root = q.top();q.pop();// 在处理右子树之前遍历res.push_back(root->val);root = root->right;}}return res;}
};
后续非递归遍历

后续遍历稍微复杂一点,这里采用先遍历:根–>右子树–>左子树的方式,然后将其结果逆序就变成了:左子树–>右子树–>根 的方式,不过逆序也可以用栈来实现

class Solution {public:vector<int> postorderTraversal(TreeNode *root) {vector<int> res;stack<TreeNode *> s1;while (!s1.empty() || root) {if (root) {res.push_back(root->val);s1.push(root);// 先遍历右子树root = root->right; } else {root = s1.top();s1.pop();root = root->left;}}reverse(res.begin(), res.end());return res;
};

宽度优先遍历(BFS):

宽度优先遍历根据队列的方式遍历,vector中的vector为每层中遍历结果。

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> q;vector<vector<int>> res;if (!root) {return res;}q.push(root);while(!q.empty()) {vector<int> tmp;int size = q.size();while(size > 0) {TreeNode* node = q.front();q.pop();tmp.push_back(node->val);if (node->left){q.push(node->left);}if (node->right) {q.push(node->right);}size--;}res.push_back(tmp);}return res;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2906392.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 常用命令(1)

&#x1f607;作者介绍&#xff1a;一个有梦想、有理想、有目标的&#xff0c;且渴望能够学有所成的追梦人。 &#x1f386;学习格言&#xff1a;不读书的人,思想就会停止。——狄德罗 ⛪️个人主页&#xff1a;进入博主主页 &#x1f5fc;专栏系列&#xff1a;Linux 随笔集合 …

必应bing国内广告推广怎么做,烧不烧钱?

必应Bing作为全球领先的搜索引擎之一&#xff0c;其国内广告平台提供了丰富而精准的广告资源&#xff0c;为众多企业带来极具性价比的品牌推广机会。然而&#xff0c;要想在必应Bing上取得理想的广告效果&#xff0c;并不一定意味着“烧钱”&#xff0c;而是需要通过科学的策略…

Spring日志框架

前言 本文我们简单说说关于Spring中的日志框架,以及对应的注解 我们知道,公司服务器在运行的时候,一定会打印日志,有很多优点,比如预防报警,或者是某重大事故尝试修复等等都需要查看日志 应该说日志对我们来说并不陌生,我们在之前刷题或者是程序遇到bug的时候也经常会将程序的状…

Databricks 开源 DBRX:一款功能强大的新型企业级语言模型

Databricks 公司发布了 DBRX&#xff0c;这是一款性能优异的大语言模型&#xff0c;在各项测试中均超越了现有的开源模型。DBRX 的目标是为企业提供高质量、可定制的 AI 工具&#xff0c;帮助企业更好地利用生成式 AI 技术。 DBRX 的一大亮点是其出色的性能。在语言理解、编程…

Redis 主从复制原理,设计的真巧妙!

前言 今天继续来看看有关 Redis 的一个问题&#xff0c;主从复制。通常&#xff0c;对于大多数的场景来说&#xff0c;读比写更多&#xff0c;于是对于缓存的水平扩展&#xff0c;其中的一个方式 “主从复制” 就是一个常见的思路。有了主从复制&#xff0c;那么可以扩展出很多…

Kibana操作Elasticsearch教程

文章目录 简介ES文档操作创建索引查看索引创建映射字段查看映射关系字段属性详解typeindexstore 字段映射设置流程 新增数据新增会随机生成id新增自定义id智能判断 修改数据删除数据查询基本查询查询所有&#xff08;match_all&#xff09;匹配查询多字段查询词条匹配多词条精确…

大模型预测,下一个token何必是文字?

太快了太快了… 大模型的生成技能&#xff0c;已经到了普通人看不懂的境界&#xff01; 它可以根据用户过去5年的体检报告&#xff0c;生成未来第1年、第2年、第3年的体检报告。 你看&#xff0c;这个生成的过程&#xff0c;是不是像极了ChatGPT&#xff0c;根据历史单词预测…

测开——测试用例设计题

1.测试手机的短信功能需要考虑哪些测试点&#xff1f; 考测试思维 是否能正常打开或进入短信界面短信可以正常编辑、修改、删除短信可以正常发送、接收短信页面的字体、颜色显示是否正常【UI界面 手机设置了字体颜色 大小是否同步】短信的字体是否能够调整同时给多个人发短信…

工业测试测量仪器与人工智能(AI)如何结合

工业测试测量仪器与人工智能&#xff08;AI&#xff09;的结合可以通过多种方式实现&#xff0c;其中一些主要方法包括&#xff1a; 1. 数据分析和预测 智能数据分析&#xff1a;利用AI算法对从传感器和测试仪器收集的数据进行分析&#xff0c;识别模式、趋势和异常&#xff0…

vue+elementUI搭建动态表头的表格

前提&#xff1a;以下代码是vue2项目结合elementUi完成的 数据结构 后端传来的数据是两个list&#xff0c;一个表头的list&#xff0c;一个表格内容的list // 表头 headTableAtts: [{ columnLabel: 姓名, columnName: name },{ columnLabel: 年龄, columnName: age },{ colu…

ensp中pc机访问不同网络的服务器

拓扑图如下&#xff0c;资源已上传 说明&#xff1a;pc通过2个路由访问server服务器 三条线路分别是192.168.1.0网段&#xff0c;192.168.2.0网段和192.168.3.0网段&#xff0c;在未配置的情况下&#xff0c;pc设备是访问不到server的 具体操作流程 第一&#xff1b;pc设备…

简单了解原型模式

什么是原型模式 区别于单例模式&#xff0c;原型模式的一个类可以有多个实例化的对象。 原型模式通过拷贝来产生新的对象&#xff0c;而不是new&#xff0c;并且可以根据自己的需求修改对象的属性。 实现Cloneable接口实现拷贝 而拷贝又分为浅拷贝和深拷贝&#xff0c;两者在…

python的神奇bug2

今天测试出一个很诡异的bug&#xff0c; 这个错误还真的很难发现 测试1 a [1,10,100] for i in a:print(i)if(i10):a[20,30,-1]一般来说我们在进行迭代时&#xff0c;a这个值时不能改动的&#xff0c;但是现在的问题时如果我不小心给改动了呢&#xff0c;结果如下 也就是说…

【数据结构刷题专题】—— 二分查找

二分查找 二分查找模板题&#xff1a;704. 二分查找 二分查找前提&#xff1a; 有序数组数组中无重复元素 左闭右闭&#xff1a; class Solution { public:int search(vector<int>& nums, int target) {int left 0;int right nums.size() - 1;while (left <…

基于unbantu的nginx的配置

目录 前言: 1.安装nginx并进行测试 1.1使用nginx -v 命令查看版本 1.2开启服务 查看端口 1.3测试 2.nginx的静态资源访问配置 2.1创建静态资源存放的目录 2.2写入目录中测试文件对应的内容 2.3修改配置文件 2.4 测试 3.虚拟主机配置 3.1创建目录 3.2写入测试…

SOLIDWORKS 2024 推荐硬件:开箱即用的配置以及升级优化的SOLIDWORKS硬件

SOLIDWORKS 2024已于2023年年末发布&#xff0c;使用SOLIDWORKS 2024的用户关注的问题之一就是&#xff1a;适合SOLIDWORKS2024这个版本的最佳硬件是什么&#xff1f; 这篇文章&#xff0c;硕迪科技将推荐SOLIDWORKS 2024的开箱即用的解决方案以及各个硬件的配置要求。 这些建议…

JavaEE 初阶篇-深入了解多线程等待与多线程状态

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 线程等待 1.1 线程等待 - join() 方法 1.1.1 main 线程中等待多个线程 1.1.2 main 线程等待 t2 线程且t2 线程等待 t1 线程 1.1.3 其他线程阻塞等待 main 线程 1.…

机器学习概论—增强学习

机器学习概论—增强学习 强化学习(Reinforcement Learning, RL)或者说是增强学习,是机器学习的一个领域,旨在使智能体通过与环境的交互学习如何做出决策,它是关于在特定情况下采取适当的行动来最大化奖励。它被各种软件和机器用来寻找在特定情况下应采取的最佳行为或路径…

在.Net6中用gdal实现第一个功能

目录 一、创建.NET6的控制台应用程序 二、加载Gdal插件 三、编写程序 一、创建.NET6的控制台应用程序 二、加载Gdal插件 Gdal的资源可以经过NuGet包引入。右键单击项目名称&#xff0c;然后选择 "Manage NuGet Packages"&#xff08;管理 NuGet 包&#xff09;。N…

视频素材免费哪个好?7个视频素材下载网站推荐

小伙帮们准备做视频的时候才发现&#xff0c;哎呀&#xff0c;高清视频素材哪里找啊&#xff1f;不用急&#xff0c;这次我们依旧从中国的宝藏网站开始&#xff0c;然后穿越全球&#xff0c;发现更多精彩的无水印视频素材网站 1&#xff0c;蛙学府&#xff08;中国&#xff09…