DAY14二叉树迭代遍历

news2024/11/25 14:47:08

二叉树前序迭代法遍历

前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。

为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。

/**
 1. Definition for a binary tree node.
 2. struct TreeNode {
 3.     int val;
 4.     TreeNode *left;
 5.     TreeNode *right;
 6.     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 7.     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 8.     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 9. };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root == nullptr) return result;
        st.push(root);//根节点入栈
        while(!st.empty()){
            TreeNode* node  =  st.top();//获取栈顶元素
            st.pop();//弹出
            result.push_back(node->val);//加入数组中
            if(node->right) st.push(node->right);//不为空,入栈
            if(node->left) st.push(node->left);//不为空,入栈
        }
        return result;
    }
};

中序遍历(迭代法)

为了解释清楚,我说明一下 刚刚在迭代的过程中,其实我们有两个操作:

处理:将元素放进result数组中
访问:遍历节点
分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢?
因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。

那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进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> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur != NULL || !st.empty()){
            if(cur != NULL){//不为空, // 指针来访问节点,访问到最底层
                st.push(cur);//栈存储遍历过的节点
                cur = cur->left;//更新cur
            }else{
                cur = st.top();
                result.push_back(cur->val);//1.左元素访问到底了,加入结果;2.是中节点
                st.pop();//弹出栈顶元素
                cur = cur->right;更新cur为右节点,再次判断
            }
        }
        return result;
    }
};

后序遍历(迭代法)

再来看后序遍历,前序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下前序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
前序到后序在这里插入图片描述

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
    }
};

总结

1.前序遍历中访问节点(遍历节点)和处理节点(将元素放进result数组中)可以同步处理,但是中序就无法做到同步!
2.迭代的时候,包括了遍历、处理两个步骤,遍历就是在访问元素;处理就是添加进返回的数组result数组中。
3.用栈来做存储节点的数据结构,先进后出,每次添加进result数组时,都是栈顶元素,然后pop()

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

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

相关文章

Stable Diffusion 如何写好提示词(Prompt)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文深入探讨了如何撰写出优质的提示词&#xff0c;内容涵盖多个维度&#xff1a;提示词的多样化分类、模型应用中的经典提示词案例、提供丰富资源的提示词参考…

基于STM32的智慧农业管理系统设计与实现

文章目录 一、前言1.1 项目介绍【1】项目功能【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 传感器功能介绍1.4 开发工具的选择 二、EMQX开源MQTT服务器框架三、购买ECS云服务器3.1 登录官网3.2 购买ECS服务器3.3 配置安全组3.4 安装FinalShell3.5 远程登录到云服…

Java代码审计工程师直播第六期

本期直播课程将深入探讨Java代码审计的关键概念和技术。涵盖课题包括安全漏洞分析、代码审查方法、常见漏洞案例分析等。学员将通过实例掌握代码审计实战技能&#xff0c;提升对Java应用程序安全的认知和技能水平。 课程大小&#xff1a;6.1G 课程下载&#xff1a;https://do…

Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 三要素

镜像、容器、镜像仓库是 Docker 中最核心的三个概念&#xff0c;组成了 Docker 的整个生命周期。 &#xff08;镜像、容器、镜像仓库三者运行关系&#xff09; 1、镜像 镜像是 Docker 的核心元素质疑&#xff0c;作为容器运行的基础&#xff0c;Docker Hub 官网提供了庞大的镜…

第十五届蓝桥杯(Web 应用开发)模拟赛 3 期-大学组(被题目描述坑惨了)

目录 1.创意广告牌 2.原子化css 3.神秘咒语 4.朋友圈 5.美食蛋白揭秘 6.营业状态变更 7.小说阅读器 8.冰岛人 9.这是一个”浏览器“ 10.趣味加密解密 总结 1.创意广告牌 这个题目不多说了&#xff0c;只要知道这些css应该都能写出来&#xff0c;不会的平时多查查文…

突破界限的力量:探索Facebook如何打破国界、文化和语言的障碍

在当今全球化的时代&#xff0c;社交媒体已经成为人们生活中不可或缺的一部分&#xff0c;而Facebook作为其中的先驱者&#xff0c;更是在打破国界、文化和语言障碍方面发挥着举足轻重的作用。它不仅成为了人们交流、连接的重要平台&#xff0c;更是为不同国家、不同文化、不同…

固态存储是未来|浅析SSD架构的演进与创新技术-1

常见的SSD架构中&#xff0c;包括了SSD控制器、NAND颗粒、DRAM颗粒三大组件&#xff0c;SSD控制器的固件需要兼顾坏块管理、ECC纠错、垃圾回收GC、磨损均衡WL、NAND die介质管理、缓存交互等等。 随着时代的发展&#xff0c;SSD架构&#xff0c;也不断有新的挑战和需求。基于小…

抓取Instagram数据:Fizzler库带您进入C#爬虫程序的世界

引言 在当今数字化的世界中&#xff0c;数据是无价之宝。社交媒体平台如Instagram成为了用户分享照片、视频和故事的热门场所。作为开发人员&#xff0c;我们可以利用爬虫技术来抓取这些平台上的数据&#xff0c;进行分析、挖掘和应用。本文将介绍如何使用C#编写一个简单的Ins…

一条 sql 语句可能导致的表锁和行锁以及死锁检测

锁 MDL 当对一个表做增删改查操作的时候&#xff0c;加 MDL 读锁&#xff1b;当要对表做结构变更操作的时候&#xff0c;加 MDL 写锁 ALTER TABLE tbl_name NOWAIT add column ... ALTER TABLE tbl_name WAIT N add column ... …

小程序bindtap 和 catchtap 的区别以及如何使用

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;我今天要和大家聊一聊小程序开发中的一个常见问题&#xff1a;bindtap 和 catchtap 的区别以及如何使用。这两个在小程序开发中经常被提及的事件绑定方式&#xff0c;它们之间到底有什么不同呢&#xff1f;让我们一起来深入探讨…

Prometheus监控Mysql数据库在Grafana展示

未安装prometheus和Grafana可以参考这个博客操作 Docker安装Prometheus监控-CSDN博客 Windows版本数据库 一、在数据库服务器安装mysqld-exporter 下载mysqld-exporter文件 Releases prometheus/mysqld_exporter GitHub 二、配置mysqld-exporter文件 1、解压进入mysqld…

微服务架构中的拆分粒度决策

大家好&#xff01;今天我来和大家分享一下微服务架构中的拆分粒度决策问题&#xff0c;希望能帮助大家更好地理解和应用微服务架构&#xff01; 问题背景 在设计和实施微服务架构时&#xff0c;拆分粒度的决策非常重要。拆分得太细&#xff0c;会增加系统间通信和部署的复杂性…

基于Springboot的驾校预约学习系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的驾校预约学习系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

12、设计模式之代理模式(Proxy)

一、什么是代理模式 代理模式属于结构型设计模式。为其他对象提供一种代理以控制对这个对象的访问。 在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;而代理对象可以在客户端和目标对象之间起到中介的作用。 二、分类 代理模式分为三类&#…

css3实现3D立方体旋转特效源码

源码介绍 CSS3自动旋转正方体3D特效是一款基于css3 keyframes属性制作的图片相册自动旋转立方体特效 效果展示 下载地址 css3实现3D立方体旋转特效代码

Go——下划线

"_"是特殊标识符&#xff0c;用来忽略结果。 1. 下划线在import中 在golang中&#xff0c;import的作用是导入其他package。 import下划线的作用&#xff1a;当导入一个包时&#xff0c;该包下的文件里所有init()函数都会被执行&#xff0c;然而&#xff0c;有些时候…

Spring Boot如何自定义自己的Starter组件?

一、为什么要自定义starter 在我们的日常开发工作中&#xff0c;经常会有一些独立于业务之外的配置模块&#xff0c;我们经常将其放到一个特定的 包下&#xff0c;然后如果另一个工程需要复用这块功能的时候&#xff0c;需要将代码硬拷贝到另一个工程&#xff0c;重新集成一 遍…

SQLiteC/C++接口详细介绍之sqlite3类(三)

上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;二&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;四&#xff09; 6.sqlite3_create_module与sqlite3_create_module_v2函数 用于创建自定义SQLite模块。创建自定义模块可以让S…

ChatGPT无法登录,提示我们检测到可疑的登录行为,将阻止进一步的尝试。请与管理员联系

1. 问题描述 之前本来已经连续稳定使用ChatGPT好几个月了&#xff0c;但是今天尝试登录ChatGPT的时候&#xff0c;却提示&#xff1a;我们检测到可疑的登录行为&#xff0c;将阻止进一步的尝试。请与管理员联系。 此外&#xff0c;我还在网上看到了一些相关的消息&#xff0c;…

Kafka的基本介绍以及扩展

文章目录 基本操作新增Topic查询Topic修改Topic删除Topic 生产者和消费者创建生产者创建消费者 Broker扩展Producer扩展Topic、Partition、Message扩展存储策略容错机制 基本操作 新增Topic 指定两个分区&#xff0c;两个副本&#xff0c;replication不能大于集群中的broker数…