代码随想录算法训练营day14|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

news2024/11/17 3:38:30

二叉树的递归遍历

首先需要明确的一点是,前序中序和后序在二叉树的递归遍历中的区别仅在于递归函数中操作的顺序,前序是在遍历一个节点的左右子树前进行操作,中序是在遍历一个节点的左子树后进行操作再遍历右子树,而后序是在遍历完左右子树再进行操作。所以在递归函数中,仅是顺序的差别。前序中序和后序可简化为中左右、左中右和左右中,此外,写递归函数时,需要明确三点:

  • 确定递归函数的参数和返回值
  • 确定终止条件
  • 确定单层递归的逻辑

        在对二叉树的递归遍历中,递归函数需要传入树节点TreeNode * cur和vec数组进行操作,无实际返回值,所以函数为void,当递归操作时,若节点为空则返回,对每层递归的逻辑以前序遍历来说,先讲当前节点的val值传入数组vec中,之后遍历左子树,再之后遍历右子树。

代码随想录 (programmercarl.com)二叉树的递归遍历icon-default.png?t=N7T8https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.html#%E6%80%9D%E8%B7%AF看到递归就晕?带你理解递归的本质!_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1UD4y1Y769/?spm_id_from=333.880.my_history.page.click&vd_source=fc4a6e70e3a87b7ea67c2024e326e7c5

前序遍历递归函数如下所示,

void traversal(TreeNode * cur, vector<int> & vec){//创建前序递归遍历函数
        if(cur == nullptr)//当当前遍历节点为空时,返回
            return;
        vec.push_back(cur->val);//中 将当前遍历节点的val值存入vec数组 *操作
        traversal(cur->left,vec);//遍历左子树
        traversal(cur->right,vec);//遍历右子树
    }

void traversal(TreeNode * cur, vector<int> & vec){//创建中序递归遍历函数
        if(cur == nullptr)//当当前遍历节点为空时,返回
            return;
        traversal(cur->left,vec);//遍历左子树
        vec.push_back(cur->val);//中 将当前遍历节点的val值存入vec数组 *操作
        traversal(cur->right,vec);//遍历右子树
    }

void traversal(TreeNode * cur, vector<int> & vec){//创建后序递归遍历函数
        if(cur == nullptr)//当当前遍历节点为空时,返回
            return;
        traversal(cur->left,vec);//遍历左子树
        traversal(cur->right,vec);//遍历右子树
        vec.push_back(cur->val);//中 将当前遍历节点的val值存入vec数组 *操作
    }

对于主函数体,只需传入节点,在函数体中创建一个ans数组,并传入traversal函数中。

vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        traversal(root,ans);
        return ans;
    }

递归遍历树节点的时间复杂度和空间复杂度均为O(n)。

二叉树的迭代遍历

前序遍历

        考虑前序递归遍历的过程,若操作为打印,则先将自身val值打印后,对所有左子树打印,然后打印右子树,考虑使用栈来模拟前序遍历的过程(也是用栈来模拟递归的过程),由于栈是先入后出的数据结构,前序遍历结果左子树节点在右子树节点前,所以需先对右子树中节点入栈,再对左子树中节点入栈。然后是大致流程,创建结果数组ans,先判断根节点是否为空,若为空直接返回结果数组,否则将根节点入栈,在一个while循环中实现二叉树的迭代前序遍历,由于栈模拟的递归过程,当栈为空时,也就意味着递归结束,即我们遍历结果结果结束。所以while的循环条件为stack.size()!=0,在循环体内,创建一个指针指向当前节点,将其val值加入ans数组,之后再弹出栈,(第一次循环的pop为根节点,即第一次前序遍历要对根节点进行操作,之后因为我们是对栈是先加入右子树节点后加入左子树节点,所以会先对节点的左子树进行操作后对节点的右子树进行操作,完成前序遍历的过程),之后判断右子树的存在,若存在,将其入栈,判断左子树的存在,存在则将其入栈,这就是循环体内内容。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> stack;
        vector<int> ans;
        if(root == nullptr){//当根节点为nullptr,直接返回ans
            return ans;
        }
        stack.push(root);
        while(stack.size()!=0){//栈不为空则循环
            TreeNode*cur = stack.top();//创建cur指针指向栈顶地址
            ans.push_back(cur->val);//将栈顶地址的值存入ans数组
            stack.pop();//出栈
            if(cur->right)//判断左右子树存在的情况,若存在,将其存入栈中,注意顺序,先右后左                
                         //出栈则为先左后右
                stack.push(cur->right);
            if(cur->left)
                stack.push(cur->left);
        }
        return ans;
    }
};

该算法的时间复杂度和空间复杂度均为O(n)。

中序遍历

        在遍历二叉树的节点时,创建遍历指针cur,先遍历左子树,依次将所有左节点全部入栈,当当前节点的左节点为空时,弹出栈中元素给遍历指针cur,并将cur指向的val传入数组中,完成中的操作,令cur = cur->right,并继续进行循环。算法的时间和空间复杂度均为O(n)。

class Solution {
public:
    // 定义一个函数,用于执行中序遍历
    vector<int> inorderTraversal(TreeNode* root) {
        // 创建一个空向量 ans,用于存储遍历的结果
        vector<int> ans;
        // 创建一个空栈 st,用于辅助遍历
        stack<TreeNode*> st;
        // 创建一个指针 cur,初始指向根节点
        TreeNode* cur = root;
        // 当 cur 指向的节点不为空或者栈 st 不为空时,进行循环
        while (cur != nullptr || !st.empty()) {
            // 如果 cur 指向的节点不为空,则将其压入栈 st 中,并移动 cur 指针到其左子节点
            if (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            }
            // 如果 cur 指向的节点为空,说明左子节点已经访问完毕,此时从栈 st 中弹出最上面的节点
            else {
                cur = st.top(); // 获取栈顶节点
                st.pop(); // 弹出栈顶节点
                // 将弹出的节点的值添加到 ans 向量中
                ans.push_back(cur->val);
                // 移动 cur 指针到其右子节点
                cur = cur->right;
            }
        }
        // 循环结束后,返回存储遍历结果的 ans 向量
        return ans;
    }
};

后序遍历

        考虑前序遍历和后序遍历的相似之处,调整一下前序遍历中左右节点的入栈顺序,让中左右变为中右左,之后再通过一个reverse即能实现后序遍历。

调整

//前序
if(cur->right)//判断左右子树存在的情况,若存在,将其存入栈中,注意顺序,先右后左                
                         //出栈则为先左后右
stack.push(cur->right);
if(cur->left)
stack.push(cur->left);

//后序
if(cur->left)
stack.push(cur->left);
if(cur->right)
stack.push(cur->right);
            

整体代码

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> stack;
        vector<int> ans;
        if(root == nullptr){//当根节点为nullptr,直接返回ans
            return ans;
        }
        stack.push(root);
        while(stack.size()!=0){//栈不为空则循环
            TreeNode*cur = stack.top();//创建cur指针指向栈顶地址
            ans.push_back(cur->val);//将栈顶地址的值存入ans数组
            stack.pop();//出栈
            if(cur->left)
                stack.push(cur->left);
            if(cur->right)
                stack.push(cur->right);
        }
        reverse(ans.begin(),ans.end());//反转
        return ans;
    }
};

二叉树的统一迭代法

周末再看看

代码随想录 (programmercarl.com)二叉树的统一迭代法icon-default.png?t=N7T8https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E7%BB%9F%E4%B8%80%E8%BF%AD%E4%BB%A3%E6%B3%95.html#%E6%80%9D%E8%B7%AF

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

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

相关文章

【DevOps】Elasticsearch在Ubuntu 20.04上的安装与配置:详细指南

目录 一、ES 简介 1、核心概念 2、工作原理 3、 优势 二、ES 在 Ubuntu 20.04 上的安装 1、安装 Java 2、下载 ES 安装包 3、创建 ES 用户 4 、解压安装包 5、 配置 ES 6、 启动 ES 7、验证安装 三、ES 常用命令 1、创建索引 2、 插入文档 3、查询文档 四、ES…

Weblogic SSRF漏洞 [CVE-2014-4210]

漏洞复现环境搭建请参考 http://t.csdnimg.cn/svKal docker未能成功启动redis请参考 http://t.csdnimg.cn/5osP3 漏洞原理 Weblogic的uddi组件提供了从其他服务器应用获取数据的功能并且没有对目标地址做过滤和限制&#xff0c;造成了SSRF漏洞&#xff0c;利用该漏洞可以向内…

git工作流程

以财务开发为例子&#xff1a; 1. 新建分支 1.1. upstream新建分支&#xff1a;finance-feature 1.2. origin新建对应分支&#xff1a;finance-feature 1.3 新建本地分支 git branch finance-feature 注&#xff1a; 同步远程分支&#xff1a;git fetch upstream feature…

【Flutter】KeyAnimatedList组件

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Flutter学习 &#x1f320; 首发时间&#xff1a;2024年5月28日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e; 目…

微软联手清华,AI注释让文本到图像生成更符合人类偏好

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 摘要 本研究展示了利用人类偏好数据集来精细调整文本到图像生成模型的潜力&#xff0c;增强了生成图像与文本提示之间的一致性。尽管取得了进展&#xff0c;现有的人类偏好数据集要么构建成…

[Algorithm][动态规划][简单多状态DP问题][买卖股票的最佳时机 III][买卖股票的最佳时机 Ⅳ]详细讲解

目录 1.买卖股票的最佳时机 III1.题目链接2.算法原理详解3.代码实现 2.买卖股票的最佳时机 IV1.题目链接2.算法原理详解3.代码实现 1.买卖股票的最佳时机 III 1.题目链接 买卖股票的最佳时机 III 2.算法原理详解 注意&#xff1a;本题为了便于初始化&#xff0c;有较多细节服…

对竞品分析的理解

一、竞品分析是什么 竞品分析即对竞争对手进行分析&#xff0c;是市场研究中的一项重要工作&#xff0c;它可以帮助企业了解竞争对手的产品、策略、市场表现等信息&#xff0c;通过竞品分析可以为自己的产品制定更加精准的策略。 二、为什么要做竞品分析 1.了解市场情况 了解…

如果创办Google

本文是一篇演讲稿&#xff0c;来自于《黑客与画家》一书的作者保罗*格雷厄姆&#xff0c;被称为硅谷创业之父。这是他为14至15岁的孩子们做的一次演讲&#xff0c;内容是关于如果他们将来想创立一家创业公司&#xff0c;现在应该做些什么。很多学校认为应该向学生们传授一些有关…

【DrissionPage爬虫库 1】两种模式分别爬取Gitee开源项目

文章目录 DrissionPage爬虫库简介1. 浏览器操控模式&#xff08;类似于游戏中的后台模拟鼠标键盘&#xff09;2. 数据包收发模式&#xff08;类似于游戏中的协议封包&#xff09; 实战中学习需求&#xff1a;爬取Gitee开源项目的标题与描述解决方案1&#xff1a;用数据包方式获…

【常用的队列总结】

文章目录 队列的介绍Queue队列的基本概念与操作队列的基本概念 常见的队列介绍非阻塞队列LinkedList:ArrayDeque:PriorityQueue: 阻塞队列ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue DelayQueueSynchronousQueue 队列的介绍 Queue队列的基本概念与操作 在 …

Linux用docker安装ElasticsearchSpringBoot整合ES

一. 部署Elasticsearch 1. docker查询docker容器中的es docker search elasticsearch 2. 安装&#xff08;PS&#xff1a;查看自己的springBoot的版本号 对应的es版本安装&#xff09; docker pull elasticsearch:7.6.23. 查看已安装的docker镜像 docker images4. 创建挂…

【会议征稿,SPIE独立出版】第五届计算机视觉和数据挖掘国际学术会议(ICCVDM 2024)

第五届计算机视觉与数据挖掘国际学术会议&#xff08;ICCVDM 2024&#xff09;将于2024年7月19-21日在中国长春举行。此前&#xff0c;ICCVDM系列会议于2020年在中国西安、2021年在中国长沙&#xff08;线上&#xff09;、2022年在中国呼伦贝尔&#xff08;线上线下&#xff09…

【Java】JavaSE概述

1、简介 Java SE&#xff08;Java Platform, Standard Edition&#xff09;是Java技术的核心平台&#xff0c;它提供了Java编程语言、Java虚拟机&#xff08;JVM&#xff09;以及Java核心类库和API。Java SE主要用于开发和部署桌面应用程序、服务器应用程序、命令行工具和嵌入…

DBeaver怎么将编辑栏内容放大

1、窗口–》编辑器–》放大 2、ctrl 3、页面结果展示

前端大师-高级Web开发测验

目录 前言 1.按正确的执行顺序排列脚本 2.哪些说法是正确的&#xff1f;&#xff08;D&#xff09; 3.填写正确的术语 4.程序的输出 5.将资源提示与其定义匹配 6.以下程序的输出是&#xff1f; 7.将PerformanceNavigationTimings按正确的顺序排列 8.将缓存指令与其定义…

【动手学PaddleX】谁都能学会的基于迁移学习的老人摔倒目标检测

本项目使用PaddleX搭建目标检测模块&#xff0c;在一个精选的数据集上进行初步训练&#xff0c;并在另一个老年人跌倒检测的数据集上进行参数微调&#xff0c;实现了迁移学习的目标检测项目。 1.项目介绍 迁移学习是非常有用的方法&#xff0c;在实际生活中由于场景多样&…

【ai】pycharm设置软件仓库编译运行基于langchain的chatpdf

联想笔记本 y9000p创建python工程: 使用langchain支持openai的向量化embedding安装软件包 发现没有openai ,添加软件仓库打开工具窗口 点击设置

osg的了解

osg开发配置与第一个osg程序-CSDN博客 #include <osg/Geode> #include <osg/ShapeDrawable> #include <osgViewer/Viewer> #include <iostream>int main(int argc, char** argv) {std::cout << "Hello, osg!" << std::endl;osg:…

加速模型训练 GPU cudnn

GPU的使用 在定义模型时&#xff0c;如果没有特定的GPU设置&#xff0c;会使用 torch.nn.DataParallel 将模型并行化&#xff0c;充分利用多GPU的性能&#xff0c;这在加速训练上有显著影响。 model torch.nn.DataParallel(model).cuda() cudnn 的配置&#xff1a; cudnn.…

MER 2024 第二届多模态情感识别挑战赛

多模态情感识别是人工智能领域的一个活跃研究课题。它的主要目标是整合多种模态来识别人类的情绪状态。当前的工作通常为基准数据集假设准确的情感标签&#xff0c;并专注于开发更有效的架构。然而&#xff0c;现有技术难以满足实际应用的需求。 清华大学陶建华教授联合中国科学…