代码随想录day12 | [前、中、后、层]二叉树的遍历迭代法和递归法

文章目录

    • 一、前后中序递归法
    • 二、前后序迭代法
    • 三、中序遍历迭代法
    • 四、层序遍历

递归三部曲:
1️⃣ 第一步确定递归函数的返回值和参数
2️⃣第二步确定递归的终止条件
3️⃣第三步确定单层递归处理的逻辑

一、前后中序递归法

前序遍历二叉树

class Solution
{
private:
    vector<int> res;

public:
    void dfs(TreeNode *root)
    {
        if (root == nullptr)
            return;

        res.push_back(root->val);
        if (root->left)
            preorderTraversal(root->left);
        if (root->right)
            preorderTraversal(root->right);
    }
    vector<int> preorderTraversal(TreeNode *root)
    {
        dfs(root);
        return res;
    }
};

二、前后序迭代法

前序遍历二叉树
借助栈来实现。
在这里插入图片描述


按理说应该是:根 左 右
但是是栈的结构,所以入孩子节点的时候,先右再左。
这样方便弹出!
在这里插入图片描述

前序遍历非递归:
class Solution
{
public:
    vector<int> preorderTraversal(TreeNode *root)
    {
        // 迭代法
        vector<int> res;
        stack<TreeNode *> st;
        if (root == nullptr)
            return res;
        st.push(root);

        while (!st.empty())
        {
        	// 每次进入循环需要先获得栈顶元素
            TreeNode *tmp = st.top(); // 根
            st.pop();
            res.push_back(tmp->val);

            if (tmp->right)
                st.push(tmp->right); // 右
            if (tmp->left)
                st.push(tmp->left); // 左
        }
        return res;
    }
};

前序遍历改为后序遍历只需要改2行,再加一行即可。
右左换一下顺序,再逆置一下res数组即可得到我们的答案。

后序遍历非递归:
class Solution
{
public:
    vector<int> preorderTraversal(TreeNode *root)
    {
        // 迭代法
        vector<int> res;
        stack<TreeNode *> st;
        if (root == nullptr)
            return res;
        st.push(root);

        while (!st.empty())
        {
        	// 每次进入循环需要先获得栈顶元素
            TreeNode *tmp = st.top(); // 根
            st.pop();
            res.push_back(tmp->val);

            
            if (tmp->left)
                st.push(tmp->left); // 左
            if (tmp->right)
            	st.push(tmp->right); // 右
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

三、中序遍历迭代法

94.二叉树的中序遍历

为何中序遍历的非递归不同?

因为访问处理的顺序和遍历的顺序是不同的。
所以我们需要一个指针来帮助我们遍历二叉树,使用栈来处理节点上的元素。

// 中序遍历使用迭代法
class Solution
{
public:
    vector<int> inorderTraversal(TreeNode *root)
    {
        // 迭代法
        vector<int> res;
        stack<TreeNode *> st;
        TreeNode *cur = root;
        while (cur != nullptr || !st.empty())
        {
            if (cur != nullptr)
            {
                st.push(cur);
                cur = cur->left; // 左
            }
            else
            {
                // cur==nullptr 那么把cur指向栈顶元素岂不是更方便迭代?
                cur = st.top();
                st.pop();
                res.push_back(cur->val); // 根
                cur = cur->right;        // 右
            }
        }
        return res;
    }
};

四、层序遍历

102.二叉树的层序遍历
要使用队列。

class Solution
{
public:
    vector<vector<int>> levelOrder(TreeNode *root)
    {
        vector<vector<int>> res;
        queue<TreeNode *> q;
        if (root != nullptr)
            q.push(root);

        while (!q.empty())
        {
            int size = q.size();
            vector<int> v;
            for (int i = 0; i < size; i++)
            {
            // 每次进入循环,都需要一个迭代变量
                TreeNode *tmp = q.front();
                q.pop(); // 每次弹出的元素就是要记录到数组的元素
                v.push_back(tmp->val);
			// 将左右孩子 加入队列
                if (tmp->left)
                    q.push(tmp->left);
                if (tmp->right)
                    q.push(tmp->right);
            }
            res.push_back(v);
        }
        return res;
    }
};

1、while() 结束条件?

当队列为空时,说明遍历完了,第一次不管三七二十一肯定是把根直接入队列。

2、为何要记录size?

因为我们不记录的话,就不知道一层树中节点数量,那么就不知道一层循环队列该弹出多少元素。

3、内层循环每次都要定义一个tmp节点?

每次循环都要定义一个节点获取我们的队头元素,方便我们每次操作这个元素,然后再把它弹出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于应用在Google Play的元数据优化

应用标题中的关键词权重最大&#xff0c;其次是简短描述中的关键词&#xff0c;最后是长描述关键词&#xff0c;了解这些就能够很好的提高应用的可见度&#xff0c;下载量和整体成功率。 1&#xff0c;标题。 Google Play最多允许标题容纳30个字符&#xff0c;关键词的频率和密…

ARP协议(地址解析协议)

文章目录 ARP协议&#xff08;地址解析协议&#xff09;MAC地址ARP协议ARP具体实现同一链路不同链路 ARP 缓存缓存查询 APR请求/响应报文 ARP协议&#xff08;地址解析协议&#xff09; MAC地址 MAC 地址的全称是 Media Access Control Address&#xff0c;即媒体访问控制地址…

flask框架的请求处理逻辑

Django 和 Flask 是 Python 的两个非常流行的 Web 框架&#xff0c;它们对 HTTP 请求的处理方式有一些区别。 在 Django 中&#xff0c;当你的应用接收到一个 HTTP 请求时&#xff0c;Django 会将请求封装为一个 HttpRequest 对象&#xff0c;然后通过视图函数的参数传递这个对…

Kubernetes_核心组件_kubelet_kubelet服务全解析(二)

文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动Po…

kafka权威指南学习以及kafka生产配置

0、kafka常用命令 Kafka是一个分布式流处理平台&#xff0c;它具有高度可扩展性和容错性。以下是Kafka最新版本中常用的一些命令&#xff1a; 创建一个主题&#xff08;topic&#xff09;&#xff1a; bin/kafka-topics.sh --create --topic my-topic --partitions 3 --replic…

【高危】Foxit 福昕PDF阅读器 Field Calculate 释放后使用漏洞(PoC)

漏洞描述 Foxit PDF阅读器是福昕软件公司推出的一款广泛使用的PDF文档阅读器。 在受影响版本中&#xff0c;由于其javascript引擎存在use-after-free漏洞&#xff0c;攻击者可以构造恶意的PDF文件&#xff0c;通过文件中包含的deletePages()等操作使福昕PDF阅读器过早删除与页…

若依分离版——解决配置双数据源oracle,mysql分页错误问题

1. 按照若依的手册配置双数据源mysql&#xff0c;oracle 2. 在service指定 数据源 DataSource(value DataSourceType.MASTER) 或者DataSource(value DataSourceType.SLAVE) Service public class SysPostServiceImpl implements ISysPostService {/*** 查询岗位信息集合* …

9.python设计模式【外观模式】

内容&#xff1a;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一个子系统更加容易使用。 角色&#xff1a; 外观&#xff08;facade&#xff09;子类系统&#xff08;subsystem classes&#xff09; UML图 举…

react实现页面动态表单设计器(自定义推拽表单)

react实现页面动态表单设计器&#xff08;自定义推拽表单&#xff09; 实现效果安装插件使用组件介绍基本设置&#xff0c;可设置控件标签&#xff0c;是否必填&#xff0c;校验规则校验规则有如下几种多选&#xff0c;下拉&#xff0c;单选可动态设置每个选择的label以及值 实…

实例025 带分隔栏的窗体

实例说明 在软件开发中&#xff0c;经常需要将界面分成几个部分&#xff0c;而且这几个部分又可以自由调整大小。运行本例&#xff0c;实例效果如图1.25所示。 技术要点 在.NET 2.0框架中可以非常轻松的实现这一功能&#xff0c;只要在窗体中加入SplitContainer控件即可。Sp…

(链表) 剑指 Offer 24. 反转链表 ——【Leetcode每日一题】

❓剑指 Offer 24. 反转链表 难度&#xff1a;简单 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 限制&#xff1a; 0 < …

Spring Boot中整合MyBatis(基于xml方式基于注解实现方式)

一、前提准备 在Spring Boot中整合MyBatis时&#xff0c;你需要导入JDBC&#xff08;不需要手动添加&#xff09;和Druid的相关依赖。 JDBC依赖&#xff1a;在Spring Boot中整合MyBatis时&#xff0c;并不需要显式地添加JDBC的包依赖。这是因为&#xff0c;当你添加mybatis-sp…

LLM Data Pipelines: 解析大语言模型训练数据集处理的复杂流程

编者按&#xff1a;在训练大语言模型的过程中,构建高质量的训练数据集是非常关键的一步&#xff0c;但关于构建大模型训练所需数据集的通用数据处理流程&#xff08;Data pipelines)的相关资料极为稀少。 本文主要介绍了基于Common Crawl数据集的数据处理流程。首先,文章概述了…

2022年圣诞节 | 用代码实现简单圣诞树

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 一、前言 本文我们用 Python 来画一棵带背景音乐效果的雪夜圣诞树以及使用 HTMLCSSJS 在页面渲染出动态圣诞树&#xff0c;所涉及到的源码均来自GitHub开源站点。 二、效果展示 Python HTMLCSSJS 三、编码实现 …

OpenTDF数据加密引擎

OpenTDF是Virtru公司的开源项目。 Virtru基于OpenTDF开发了用于google Workspace和Microsoft 365的相关数据安全产品。 简介 virtru公司基于opentdf开发挺多产品的,都是数据安全类产品。 能把opentdf开源,已经非常不容易了。 opentdf的代码看起来还是比较整齐和成熟的。…

aPaaS开发 VS 传统软件开发?

aPaaS开发 VS 传统软件开发&#xff1f;aPaaS的优势和平台选型&#xff1a; &#xff08;1&#xff09;aPaaS模式具备成本优势、开发速度快、多场景适用等特点&#xff0c;在资本市场备受关注&#xff1b; &#xff08;2&#xff09;aPaaS能够覆盖企业销售、项目管理、业务财…

微服务远程调用openFeign简单回顾

目录 一. OpenFeign简介 二. OpenFeign原理 演示使用 provider模块 消费者模块 配置全局feign日志 示例源代码: 一. OpenFeign简介 OpenFeign是SpringCloud服务调用中间件&#xff0c;可以帮助代理服务API接口。并且可以解析SpringMVC的RequestMapping注解下的接口&#x…

学习day52

1.关于 error Component name "School" should always be multi-word vue/multi-word-component-names 这里是因为脚手架的规范原因&#xff0c; 解决办法&#xff1a; 我是在vue.comfig.js文件中加入了一条配置&#xff0c;即 lintOnSave:false 整个文件的完整…

Java 实现提取富文本中包含特定字符串的图片 src 属性值

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

Nginx配置server_name讲解

文章目录 1.Nginx配置中没有server_name会怎样&#xff1f;2.Nginx配置server_name的匹配规则3.正则表达式规则 1.Nginx配置中没有server_name会怎样&#xff1f; 此时Nginx会自动设置成 server_name ""; 它不会匹配任何域名&#xff0c;导致Nginx会优先将HTTP请求交…