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

代码随想录 二叉树 test 2

二叉树的非递归遍历

先序

方法一:

先保存根节点,用来之后找到右子树(利用栈来回溯到根,进而找到右子树)

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列stack<TreeNode*> stk;TreeNode* p = root;while(p || !stk.empty()){if(p != nullptr){   res.push_back(p->val);  //访问根节点stk.push(p);p = p->left;    //移动到左子树}else{  //如果左子树为空,就需要访问上一个结点的右子树p = stk.top();stk.pop();p = p->right;}}return res;}
};

方法二:

不用回溯,利用栈的先进后出性质,先将右子树入栈,再将左子树入栈,实现根左右。

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {if(!root) return {};vector<int> res;    //存遍历序列stack<TreeNode*> stk;stk.push(root);while(!stk.empty()){TreeNode* p = stk.top();stk.pop();res.push_back(p->val);    //根if(p->right) stk.push(p->right);    //将非空的右孩子压栈if(p->left) stk.push(p->left);    //将非空的左孩子压栈}return res;}
};

方法三:统一迭代法

每次以根节点为处理对象,如果当前遍历的结点非空,则按照右左根顺序,将三个结点都压入栈中,在压入根节点之后继续压入空指针,因此处理顺序与出栈顺序对应。如果为空,则当前该结点需要输出。

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列if(!root)   return res;stack<TreeNode*> stk;stk.push(root);while(!stk.empty()){TreeNode* p = stk.top();if(p != nullptr){stk.pop();if(p->right) stk.push(p->right);   //右if(p->left) stk.push(p->left);  //左stk.push(p);    //中stk.push(nullptr);  //标记在空结点之下即为要处理的结点}else{stk.pop();  //弹出空结点p = stk.top();  //访问要处理的结点stk.pop();  //弹出已处理好的结点res.push_back(p->val);}}return res;}
};

中序

方法一


与先序方法一类似,将访问结点操作放在遍历到当前最左结点之后。

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列stack<TreeNode*> stk;TreeNode* p = root;while(p || !stk.empty()){if(p != nullptr){   stk.push(p);p = p->left;    //移动到左子树}else{  //如果左子树为空,就需要访问上一个结点的右子树p = stk.top();stk.pop();res.push_back(p->val);  //访问左p = p->right;}}return res;}
};

方法二:统一迭代法

只需将先序中的统一迭代法,按照右根左入栈即可。

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列if(!root)   return res;stack<TreeNode*> stk;stk.push(root);while(!stk.empty()){TreeNode* p = stk.top();if(p != nullptr){stk.pop();if(p->right) stk.push(p->right);   //右stk.push(p);    //中stk.push(nullptr);  //标记在空结点之下即为要处理的结点if(p->left) stk.push(p->left);  //左}else{stk.pop();  //弹出空结点p = stk.top();  //访问要处理的结点stk.pop();  //弹出已处理好的结点res.push_back(p->val);}}return res;}
};

后序

方法一

改写先序方法一,由于遍历顺序要求是左右根,因此回溯的情况既可能是遍历完左子树也可能是遍历完右子树。如果是遍历完左子树且有右子树且右子树未被遍历过,则需要继续遍历右子树,如果是遍历完右子树,则此时栈顶元素即为当前最右,需要进行处理,处理完最右结点需要回溯到根,因此需要将当前指针置为空,在下一次循环就可以取出栈顶根。由上可知需要标记结点是否被遍历过,因此需要一个指针r记录上一个遍历过的结点。

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列stack<TreeNode*> stk;TreeNode* p = root;TreeNode* r = nullptr;while(p || !stk.empty()){if(p != nullptr){   stk.push(p);p = p->left;    //移动到左子树}else{  //如果左子树为空,就需要检查右子树状态p = stk.top();if(p->right && r != p->right){  //如果有右子树且未被遍历过p = p->right;}else{  //否则应该处理栈顶元素p = stk.top();stk.pop();res.push_back(p->val);  //处理栈顶r = p;  //标记此结点已被处理p = nullptr;}}}return res;}
};

方法二:改写先序方法二+反转

先序方法二颠倒左右子树入栈顺序实现根右左,再进行反转,变成左右根。

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {if(!root) return {};vector<int> res;    //存遍历序列stack<TreeNode*> stk;stk.push(root);while(!stk.empty()){TreeNode* p = stk.top();stk.pop();res.push_back(p->val);    //根if(p->left) stk.push(p->left);    //将非空的左孩子压栈if(p->right) stk.push(p->right);    //将非空的右孩子压栈}reverse(res.begin(), res.end());    //反转数组return res;}
};

方法三:统一迭代法

按照根右左顺序入栈

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> res;    //存遍历序列if(!root)   return res;stack<TreeNode*> stk;stk.push(root);while(!stk.empty()){TreeNode* p = stk.top();if(p != nullptr){stk.pop();stk.push(p);    //中stk.push(nullptr);  //标记在空结点之下即为要处理的结点if(p->right) stk.push(p->right);   //右if(p->left) stk.push(p->left);  //左}else{stk.pop();  //弹出空结点p = stk.top();  //访问要处理的结点stk.pop();  //弹出已处理好的结点res.push_back(p->val);}}return res;}
};

相关文章:

代码随想录 二叉树 test 2

二叉树的非递归遍历 先序 方法一: 先保存根节点&#xff0c;用来之后找到右子树(利用栈来回溯到根&#xff0c;进而找到右子树) class Solution { public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res; //存遍历序列stack<TreeNode*…...

浏览器默认语言与页面访问统计问题二三则

文章目录 前言网站默认语言问题网站访问统计问题Error: Empty components are self-closingError: A space is required before closing bracket 总结 前言 看标题大概能猜到这是一篇杂合体的总结&#xff0c;是这两天处理网站遇到的小问题&#xff0c;怕过段时间再忘了所以总…...

用Python绘制一只懒羊羊

目录 一、准备工作 二、Turtle库简介 三、绘制懒羊羊的步骤 1. 导入Turtle库并设置画布 2. 绘制头部 3. 绘制眼睛 4. 绘制嘴巴 5. 绘制身体 6. 绘制四肢 7. 完成绘制 五、运行代码与结果展示 六、总结 在这个趣味盎然的技术实践中,我们将使用Python和Turtle图形…...

虹科分享 | 汽车NVH小课堂之听音辨故障

随着车主开始关注汽车抖动异响问题&#xff0c;如何根据故障现象快速诊断异响来源&#xff0c;成了汽修人的必修课。 一个比较常用的方法就是靠“听”——“听音辨故障”。那今天&#xff0c;虹科Pico也整理了几个不同类型的异响声音&#xff0c;一起来听听看你能答对几个吧 汽…...

论文速读|SigLIP:Sigmoid Loss for Language Image Pre-Training.ICCV23

论文地址&#xff1a;https://arxiv.org/abs/2303.15343v4 代码地址&#xff1a;https://github.com/google-research/big_vision bib引用&#xff1a; misc{zhai2023sigmoidlosslanguageimage,title{Sigmoid Loss for Language Image Pre-Training}, author{Xiaohua Zhai and…...

深度学习笔记——循环神经网络之LSTM

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍面试过程中可能遇到的循环神经网络LSTM知识点。 文章目录 文本特征提取的方法1. 基础方法1.1 词袋模型&#xff08;Bag of Words, BOW&#xff09;工作…...

算法整理:2-opt求解旅行商(Python代码)

文章目录 算法思想算法步骤代码1纯函数代码2纯函数数据可视化 算法思想 通过交换边进行寻优。 算法步骤 把初始解作为当前解 通过交换边生成新解 如果新解优于历史最优解&#xff0c;则更新当前解为新解 重复2&#xff0c;3&#xff0c;直到当前解交换了所有的边均不能改…...

状态模式

在软件开发过程中&#xff0c;我们经常会遇到这样的情况&#xff1a;一个对象的行为会随着其内部状态的改变而发生变化。例如&#xff0c;一个手机在不同状态下&#xff08;开机、关机、静音等&#xff09;对相同的操作&#xff08;如来电&#xff09;会有不同的反应。传统的解…...

RoHS 简介

RoHS&#xff08;Restriction of Hazardous Substances Directive&#xff0c;限制有害物质指令&#xff09;是欧盟制定的一项环保法规&#xff0c;旨在限制电气和电子设备中某些有害物质的使用&#xff0c;以减少这些产品对环境和人体健康的危害。 RoHS限制的有害物质及其限量…...

【Vim Masterclass 笔记26】S11L46:Vim 插件的安装、使用与日常管理

文章目录 Section 11&#xff1a;Vim PluginsS11L46 Managing Vim Plugins1 第三方插件管理工具2 安装插件使用的搜索引擎3 Vim 插件的安装方法4 存放 Vim 插件包的路径格式5 示例一&#xff1a;插件 NERDTree 的安装6 示例二&#xff1a;插件 ctrlp.vim 的安装7 示例三&#x…...

深度学习原理与Pytorch实战

深度学习原理与Pytorch实战 第2版 强化学习人工智能神经网络书籍 python动手学深度学习框架书 TransformerBERT图神经网络&#xff1a; 技术讲解 编辑推荐 1.基于PyTorch新版本&#xff0c;涵盖深度学习基础知识和前沿技术&#xff0c;由浅入深&#xff0c;通俗易懂&#xf…...

ELK环境搭建

文章目录 1.ElasticSearch安装1.安装的版本选择1.SpringBoot版本&#xff1a;2.4.2 找到依赖的spring-data-elasticsearch的版本2.spring-data-elasticsearch版本&#xff1a;4.1.3 找到依赖的elasticsearch版本3.elasticsearch版本&#xff1a;7.9.3 2.安装1.官方文档2.下载压…...

基于Springboot + vue实现的民俗网

“前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能学习网站” &#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜…...

第24篇 基于ARM A9处理器用汇编语言实现中断<六>

Q&#xff1a;怎样设计ARM处理器汇编语言程序使用定时器中断实现实时时钟&#xff1f; A&#xff1a;此前我们曾使用轮询定时器I/O的方式实现实时时钟&#xff0c;而在本实验中将采用定时器中断的方式。新增第三个中断源A9 Private Timer&#xff0c;对该定时器进行配置&#…...

【数据结构】_不带头非循环单向链表

目录 1. 链表的概念及结构 2. 链表的分类 3. 单链表的实现 3.1 SList.h头文件 3.2 SList.c源文件 3.3 Test_SList.c测试文件 关于线性表&#xff0c;已介绍顺序表&#xff0c;详见下文&#xff1a; 【数据结构】_顺序表-CSDN博客 本文介绍链表&#xff1b; 基于顺序表…...

golang 使用双向链表作为container/heap的载体

MyHeap&#xff1a;container/heap的数据载体&#xff0c;需要实现以下方法&#xff1a; Len&#xff1a;堆中数据个数 Less&#xff1a;第i个元素 是否必 第j个元素 值小 Swap&#xff1a;交换第i个元素和 第j个元素 Push&#xff1a;向堆中追加元素 Pop&#xff1a;从堆…...

C#集合操作优化:高效实现批量添加与删除

在C#中&#xff0c;对集合进行批量操作&#xff08;如批量添加或删除元素&#xff09;通常涉及使用集合类型提供的方法和特性&#xff0c;以及可能的循环或LINQ查询来高效地处理大量数据。以下是一些常见的方法和技巧&#xff1a; 批量添加元素 使用集合的AddRange方法&#x…...

142.WEB渗透测试-信息收集-小程序、app(13)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;141.WEB渗透测试-信息收集-小程序、app&#xff08;12&#xff09; 软件用法&#xff0c…...

24.日常算法

1. 数组中两元素的最大乘积 题目来源 给你一个整数数组 nums&#xff0c;请你选择数组的两个不同下标 i 和 j&#xff0c;使 (nums[i]-1)*(nums[j]-1) 取得最大值。请你计算并返回该式的最大值。 示例 1&#xff1a; 输入&#xff1a;nums [3,4,5,2] 输出&#xff1a;12 解释…...

分布式理解

分布式 如何理解分布式 狭义的分布是指&#xff0c;指多台PC在地理位置上分布在不同的地方。 分布式系统 分布式系**统&#xff1a;**多个能独立运行的计算机&#xff08;称为结点&#xff09;组成。各个结点利用计算机网络进行信息传递&#xff0c;从而实现共同的“目标或者任…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...