【数据结构与算法】力扣:二叉树的前、中、后序遍历

news2024/12/25 9:22:12

递归法

前序遍历

给你二叉树的根节点 root ,返回它节点值的前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

递归:
1.规定递归的函数的参数和返回值
参数:一个指针TreeNode* cur
返回值:结果是一个数组:vector<int>& vec
2.确定终止条件。深度优先搜索,遇到空指针才停止

if(cur == NULL)
return;

3.确定单层递归的逻辑

vec.push(cur->val);//根
traversal(cur->left,vec);//左
traversal(cur->right,vec);//右

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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;
    }
};

中序遍历

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;
    }
};

后序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root,result);
        return result;

    }
};

迭代法

前序遍历(根左右)

【分析】编程语言中,常用“栈”来实现递归,用迭代法模拟递归也用栈。

在这里插入图片描述

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;//定义一个栈保存树中的结点
        vector<int> res;
        if(root == NULL) return res;
        st.push(root);//先把根结点放入栈中
        while(!st.empty())
        {
            TreeNode* node = st.top();//树的根节点就是栈顶元素
            st.pop();//将当前栈顶元素弹出
            res.push_back(node->val);
            if(node->right)st.push(node->right);//将栈顶元素的右孩子入栈
            if(node->left)st.push(node->left);//将栈顶元素的左孩子入栈
        }
        //一遍遍历结束,到了左子树的根节点,即上一个结点的左孩子,即此时栈的栈顶元素
        return res;

    }
};

后序遍历(左右根)

上文中前序遍历的顺序是:中->左->右
改为:中->右->左
再翻转数组:左->右->中

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> res;
        //vector<int> rres;
        if(root == NULL)return res;
        st.push(root);
        while(!st.empty())
        {
            TreeNode* node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->left) st.push(node->left);
            if(node->right) st.push(node->right);
        }
      reverse(res.begin(),res.end());
        return res;
    }
};

中序遍历

在这里插入图片描述
左孩子为空将栈顶元素加到数组里;右孩子为空,弹出栈顶元素。

模拟例子中的步骤

  • 从根节点开始向左遍历。根节点为5
cur = root;
  • 一直到遍历到最左端,一路向左,将指针经过的所有左结点放入栈中,直到再无左结点可遍历时停止。当栈为空时,也停止遍历。将5、4、1依次放入栈中
while(cur!=NULL || !st.empty())
{
	if(cur != NULL)
	{
		st.push(cur);
		cur = cur->left;
	}
  • 访问到最左端结点1,1没有左孩子了。取栈顶结点1(即最近访问过的结点),将其弹出栈,加入到数组(加入到数组的结点都是要处理的),遍历此时取出来的栈顶结点1的右孩子
else
{
	cur = st.top();
	st.pop();
	res.push_back(cur->val);
	cur = cur->right;
}
}
  • 结点1的右孩子也为空,执行的还是else分支,即弹出栈顶元素,此时栈顶元素为4,将4加入数组,处理结点4,4的右孩子为2
  • 此时cur->val=2,执行if分支,将2加入栈中
  • 执发现2的左孩子为空,执行else,弹出栈顶元素2,并加入数组,发现2的右孩子也为空
  • 执行else取此时栈顶元素5,将5加入数组,取5的右孩子6
  • 执行if将6入栈并发现6无左孩子,执行else,将6弹出栈,最终栈空,循环停止,程序结束
    对于第一遍遍历就存在栈中的元素,取出来放到数组中时要做的操作的只有访问右节点,但是若其含有右节点则需要将其右节点从头执行循环,要新加入栈中。即对于不是第一遍遍历就在栈中的节点,会多了个if操作

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur!=NULL || !st.empty())
        {
            if(cur!=NULL)
            {
                st.push(cur);//如果访问到的元素不为空 就把它记录到栈里 即记录指针指过的元素
                cur = cur->left;//指针一路向左
            }
            //遇到了空结点
            else
            {
                cur = st.top();//记录最近访问过的结点 即栈顶元素
                st.pop();//将其弹出栈 放入数组
                res.push_back(cur->val);
                cur = cur->right;//遍历当前指针的右孩子
                }
            }
            return res;
            }
};

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

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

相关文章

IPO后,北森驶向HR SaaS深水区

透过这次发布会&#xff0c;能感知到的依旧是北森马不停蹄的“加速度”&#xff0c;纪伟国口中不断重复的“以客户为中心”&#xff0c;以及不断开放兼容的生态。 作者| 皮爷 出品|产业家 北森&#xff0c;还是那个北森。 在刚刚举办的“HR SaaS未来势”2023北森春季产品…

Vscode搭建开发调试STM32环境IDE

单片机开发IDE环境如KeilMDK&#xff0c;虽然操作简单&#xff0c;方便调试。但就是代码编辑风格很老套&#xff0c;中文符号乱码还是常有的事。而如今流行的vscode编辑器很不错&#xff0c;免费且相当轻量级&#xff0c;用来代码开发体验很不错&#xff0c;看着都舒服。Clion …

swagger在spring项目中的使用

一、Swagger2介绍 前后端分离开发模式中&#xff0c;api文档是最好的沟通方式。 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 及时性 (接口变更后&#xff0c;能够及时准确地通知相关前后端开发人员)规范性 (并且保…

电子科技大学计算机系统结构复习笔记(一):概述

目录 前言 重点一览 计算机分类 弗林分类法 市场分类 计算机系统结构定义 实现技术\功耗\成本的趋势\可靠性(了解) 计算机性能 性能评价指标 性能评价方法 计算机设计的量化原则 基本方法 Amdahl‘s 定律 CPU 性能公式 / 时间计算 本章小结 前言 本复习笔记基于…

windows环境使用clion搭建redis5.0 redis6.0的源码阅读环境

1、下载cygwin https://cygwin.com/install.html 第一步选择从互联网安装 别放在C盘 选择直接连接 我这边选择的是163的节点 接下来&#xff0c;就是让我们选择要安装的东西&#xff0c;网上一般给的就是如下几个&#xff1a; gcc-core、gcc-g、make、gdb、binutils 一个个…

计算机视觉 | 人体关键点检测与MMPose

前言 人体姿态估计&#xff08;Human Pose Estimation&#xff09;是计算机视觉领域中的一个重要研究方向&#xff0c;也是计算机理解人类动作、行为必不可少的一步&#xff0c;人体姿态估计是指通过计算机算法在图像或视频中定位人体关键点&#xff0c;目前被广泛应用于动作检…

0x34RequestDownload请求下载

0x34RequestDownload 客户端请求协商从客户端到服务器的数据传输。 客户端使用requestDownload服务来启动从客户端到服务器的数据传输&#xff08;下载&#xff09; 。 服务器收到requestDownload请求消息后&#xff0c;服务器应在发送肯定响应消息之前采取所有必要的操作来接…

【手撕Spring源码】深度理解SpringMVC【上】

文章目录 DispatcherServletRequestMappingHandlerMappingRequestMappingHandlerAdapter自定义参数处理器自定义返回值处理器 参数解析器获取参数名对象绑定与类型转换底层第一套转换接口与实现底层第二套转换接口与实现高层转换接口与实现自定义转换器 ControllerAdvice 之 In…

NeRF与三维重建专栏(二)NeRF原文解读与体渲染物理模型

前言 上一章中我们大致介绍了三维重建的背景、NeRF应用于三维重建的难点以及相关数据集和评估指标&#xff0c;本章节将会详细介绍NeRF原文以及部分源码&#xff0c;以及体渲染的物理模型&#xff0c;来帮助读者更好理解NeRF&#xff1b;下一章我们将会结合colmap&#xff0c;讲…

PrivateGPT(如何部署及使用感受)

前言 最近在GitHub上出现了一个名为PrivateGPT的开源项目。该项目旨在为面临敏感数据、涉密信息或个人隐私问题的用户提供一种新的聊天工具。PrivateGPT具备完整的数据控制能力&#xff0c;使用户能够在本地环境中与强大的语言模型进行交互&#xff0c;无需上传数据到互联网或…

kotlin的for循环遍历

kotlin的for循环遍历 1、List val list listOf("A", "B", "C")for (item in list) {println(item)} A B C 2、List的in val list listOf("A", "B", "C")for (item: String in list) {println(item)} A B C 3、l…

【C/C++】基础知识之命名空间与作用域

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

【学习日记2023.6.2】之 管理端报表统计

文章目录 11. 管理端报表统计11.1 Apache ECharts11.1.1 介绍11.1.2 入门案例 11.2 营业额统计11.2.1 需求分析和设计11.2.2 代码开发Controller层Service层接口Service层实现类Mapper层 11.2.3 功能测试11.2.4 提交代码 11.3 用户统计11.3.1 需求分析和设计11.3.2 代码开发Con…

【QCA6174】QCA6174认证DFS跳转信道距离干扰信道太近,导致边带可以检测到信号问题分析及解决方案

WIFI DFS测试要求 Master设备需要测试的项目 4.6.2.1 Channel Availability Check ---信道可用性检查 定义其作为雷达脉冲检测机制,当雷达脉冲出现时所占用的信道需要能被设备检测到已经被占用。当相关信道未被占用时,这些信道被称为Avaliable Channel可用信道 4.6.2.2 In…

23Java面试专题 八股文面试全套真题(含大厂高频面试真题)多线程

文档说明 在文档中对所有的面试题都进行了 难易程度和 出现频率的等级说明 星数越多代表权重越大&#xff0c;最多五颗星&#xff08;☆☆☆☆☆&#xff09; 最少一颗星&#xff08;☆&#xff09; Java多线程相关面试题 1.线程的基础知识 1.1 线程和进程的区别&#xff1f; 难…

敷尔佳三闯IPO:去年狂赚8亿,广告宣传费近4亿

618大促已经开启&#xff0c;敷尔佳能否借“618”撑起“医美面膜第一股”&#xff1f; 近日&#xff0c;哈尔滨敷尔佳科技发展有限公司&#xff08;下称“敷尔佳”&#xff09;更新招股书&#xff0c;继续冲刺“医美面膜第一股”。 敷尔佳是一家主要从事专业皮肤护理产品的研…

MySQL中的业务数据该如何正确导入到Hive中 - Sqoop

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 1. 使用Sqoop脚本将MySQL中的数据迁移到HDFS 2. 在Hive中建立与之对应的表 3. 将HDFS中的数据load到 Hive 数仓的ODS层的表中 1 . 使用Sqoop 将 MySQL中的数据导入到HDFS上 #! /bin/bashsqoo…

二进制安装Kubernetes(K8s)集群(基于containerd)---从零安装教程(带证书)

一、实验环境 1、安装说明 selinux iptables off 官方网站&#xff1a;https://kubernetes.io/zh-cn/docs/home 主机名IP系统版本安装服务master0110.10.10.21rhel7.5nginx、etcd、api-server、scheduler、controller-manager、kubelet、proxymaster0210.10.10.22rhel7.5nginx、…

Ubuntu安装ssh并开启服务

Ubuntu开启SSH服务 1、更新源列表 $ sudo apt-get update 2、安装 说明:安装时需要提供互联网或者提前下载安装包 $ sudo apt-get install openssh-server 3、启动 $ sudo service ssh start 查询服务启动状态: $ sudo ps -e | grep ssh 或者 $ sudo service ssh status …

【C++】模板(1)

文章目录 前言一、泛型编程二、模板2.1 函数模板2.2 函数模板实例化&#xff1a;2. 3 函数模板的原理&#xff1a;2.4 模板参数的匹配原则 三、类模板 前言 C中的模板(template)是一种强大的语言特性&#xff0c;它可以让程序员编写可以适用于不同数据类型的通用代码。通过使用…