二叉树前序中序后序遍历(非递归)

大家好,又和大家见面啦!今天我们一起去看一下二叉树的前序中序后序的遍历,相信这个对大家来说是信手拈来,但是,今天我们并不是使用常见的递归方式来解题,我们采用迭代方式解答。我们先看第一道前序遍历 

1、前序遍历

二叉树的前序遍历

前序遍历是先将二叉树的根节点遍历,再遍历左子树、右子树。我们做这道题的思想是把二叉树划分为两部分,一是左路节点,二是左路节点的右子树。什么是左路节点,如上图的二叉树来说,

这就算以8为根节点的二叉树的左路节点,也就是以8为根节点,它的左孩子的左孩子的左孩子......这一条路径。我们先让左路节点入栈,因为是前序遍历,所以我们入栈的同时,遍历当前结点的val,当左路结点都入栈完,那么当前节点一定是没有左子树的,我们让这个结点出栈,这个时候我们处理当前结点的右子树,右子树同样进行先让左路节点入栈.....循环做此操作,直到右子树也会空,然后将这个结点的所有左右子树我们都访问完成,我们已经pop掉这个时候,只需要处理新的栈顶元素就可以啦。

话不多说,思路就是这个样子,下面把代码写出来让大家看看。

定义一个cur从根节点开始,然后定义一个栈存储左路结点,一个vector存储左路节点的数据。

vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur=root;//cur从根节点开始

        while(cur)
        {
            while(cur)
            {
                v.push_back(cur->val);
                st.push(cur);//左路结点入栈
                cur=cur->left;
            }
            //处理栈内的右子树
            TreeNode* top=st.top();
            st.pop();
            cur=top->right;//处理左路节点的右子树

        }
        return v;
    }

代码写起来很简单,但是我们会发现这个提交是过不了的,为什么呢?大家看,我们在把1的右节点赋给cur去处理1的右子树时,结点1是没有右结点的,这个时候cur为空,上面这个大循环就进不去,而这个时候,我们其它的左路节点都还在栈里面没有处理,所以,外面这个大循环的判断条件是不正确的。应该改成

while(cur||!st.empty())

当栈不为空的时候,我们也要处理。 然后我们再运行,就可以通过了。

2、中序遍历

二叉树的中序遍历

我们还是拿这棵树来看,其实中序和前序思路是完全一样,只不过前序的遍历顺序是根左右,我们左路结点入栈的时候就可以直接访问其val,但是中序遍历的顺序是左根右,所以我们写中序的时候应该把访问val的顺序调到结点出栈的时候访问就可啦。

下面我们开始实现

vector<int> inorderTraversal(TreeNode* root) {
    stack<TreeNode*> st;
    vector<int> v;
    TreeNode* cur=root;
    while(cur||!st.empty())
    {
        while(cur)//左路结点进栈
        {
            st.push(cur);
            cur=cur->left;
        }
        TreeNode* top=st.top();
        v.push_back(top->val);
        st.pop();
        cur=top->right;//处理当前结点的右子树
    }
    return v;
    }

3、后序遍历

二叉树的后序遍历

后序遍历的遍历顺序是左右根,我们只有把左右结点全部访问完成才能访问根节点的数据,或者左右节点为空才能直接访问根节点的数据。左节点我们在左路子树入栈的时候就算是访问,但是右节点怎么解决呢?

所以说,我们这里需要解决一下,怎么才能知道右节点已经访问过了。我们以这里的结点6为例,要访问结点6的val,首先,我们把8,3,1入栈,结点1没有右子树,可以直接获取它的val,出栈后,栈顶元素是3,3有右子树,需要先处理它的右树,,然后6,4入栈,这时栈顶结点为4,4没有右树,直接获取它的val,此时栈顶元素为6,6他有右树,需要先处理他的右树,此时结点7入栈,这个时候7没有右树,直接获取它的val,这个时候结点6的左右树都访问完毕,可以访问6的val了,但是我们怎么判断结点6的左右树都已经访问完毕了呢?结点6上一次访问的结点是7,我们只需要判断,6结点的上一次访问的结点是不是7就可以了。

我们可以定义一个结点prev,每访问完一个栈顶元素,我们就把top赋给prev,表示上一个访问结点,我们只需要判断top->right==prev,即我们已经访问过top->right这个结点就行了,这样我们可以直接获取栈顶的val值。

因此,只有在当前结点的右树为空,或者当前结点的右结点是我们上一次访问的结点,我们就可以获取它的val值。

下面我们开始写代码

vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur=root;
        TreeNode* prev=nullptr;
        while(cur||!st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode* top=st.top();
            //分情况讨论,如果当前这个结点的右子树为空,或者当前结点的右子树是我们上次访问的结点;表示我们已经访问过它的子树,就可以直接获取当前结点的val
            if(top->right==nullptr||top->right==prev)
            {
                st.pop();
                v.push_back(top->val);
                prev=top;
            }
            //否者,访问这个结点的右树
            else{
                cur=top->right;
            }
        }
        return v;

到这里,二叉树的前序中序后序三个非递归方式就讲解完毕啦。我们下次再见呀

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

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

相关文章

基于Robei EDA实现FIFO(非IP核)及FIFO求和

一、FIFO简介 FIFO&#xff08; First in First out&#xff09; 使用在需要产生数据接口的部分&#xff0c;用来存储、缓冲在两个异步 时钟之间的数据传输。在异步电路中&#xff0c;由于时钟之间周期和相位完全独立&#xff0c;因此数据丢失概 率不为零。使用 FIFO 可以在两个…

【ChatIE】论文解读:Zero-Shot Information Extraction via Chatting with ChatGPT

文章目录 介绍ChatIEEntity-Relation Triple Extration (RE)Named Entity Recognition (NER)Event Extraction (EE) 实验结果结论 论文&#xff1a;Zero-Shot Information Extraction via Chatting with ChatGPT 作者&#xff1a;Xiang Wei, Xingyu Cui, Ning Cheng, Xiaobin W…

【电源】POE系统供电原理(二)

转载本博客文章&#xff0c;请注明出处 ​ 上一篇文章中&#xff0c;有提到POE系统工作原理及动态检测机制&#xff0c;下面我们继续介绍受电端PD技术及原理。POE供电系统包含PSE、PD及互联接口部分组成&#xff0c;如下图所示。 图1 POE供电系统 PSE控制器的主要作用&#xff…

无人机基本知识,无人机遥控器功能详解与调试方法

无人机作为一种新兴的飞行器&#xff0c;近年来在各个领域得到了广泛的应用。而无人机遥控器则是控制无人机飞行的重要工具。 无人机遥控器是一种无线设备&#xff0c;通过它来远程控制无人机的飞行。遥控器通常包括一个或多个摇杆&#xff0c;用于控制无人机的各种动作&#x…

FL Studio 21中文破解激活版2024免费下载安装图文教程

FL Studio 21.2.1.3859中文破解激活版是我见过更新迭代最快的宿主软件&#xff0c;没有之一。FL Studio12、FL Studio20、FL Studio21等等。有时甚至我刚刚下载好了最新版本&#xff0c;熟悉了新版本一些好用的操作&#xff0c;Fl Studio就又推出了更新的版本&#xff0c;而且F…

【STM32 CubeMX】串口编程DMA+IDLE中断

文章目录 前言一、为什么要引入IDLE中断二、IDLE中断使用方式2.1 接收的三种情况2.2 函数的使用查询方式中断方式DMA方式分析一个问题 总结 前言 在嵌入式系统中&#xff0c;串口通信是一项关键的任务&#xff0c;而使用DMA&#xff08;直接内存访问&#xff09;结合IDLE中断进…

基于springboot特产销售平台源码和论文

“互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多藏区特产销售信息仍是通过人工管理的方式进行&#xff0c;需要在各个岗位投入大量的人力进行很多重复性工作&#xff0c;使得对人力物力造成诸多浪费&#xff0c;工作效率不高等情况&…

【初始RabbitMQ】工作队列的实现

工作队列 工作队列&#xff08;又称为任务队列&#xff09;的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进 程将弹出任务并最终执行作业。当有多个工作线程…

电脑屏幕录制工具 Top10 榜单,免费无水印方法集

随着媒体行业的突飞猛进&#xff0c;不同服务之间对有效屏幕录制的竞争日益激烈。这导致市场上出现了质量参差不齐的屏幕录像机。特别是有些录屏器会自动给你录制的视频加上水印&#xff0c;给需要在公共场合使用的人留下不专业的印象。除此之外&#xff0c;它们甚至不能保护您…

【Google Bard】免费生成图像——功能和使用方法详解

Google Bard 关于Bard 图片生成功能打开Bard通过Bard来生成图片Bard Vs Bing Vs Dall-EBard的生成结果Bing的生成结果Dall-E 的生成结果 总结 关于Bard 图片生成功能 Google在2月1日&#xff08;当地时间&#xff09;宣布&#xff0c;其对话型AI“Bard”新增了图像生成功能。 …

Mysql——update更新数据的方式

注&#xff1a;文章参考&#xff1a; MySQL 更新数据 不同条件(批量)更新不同值_update批量更新同一列不同值-CSDN博客文章浏览阅读2w次&#xff0c;点赞20次&#xff0c;收藏70次。一般在更新时会遇到以下场景&#xff1a;1.全部更新&#xff1b;2.根据条件更新字段中的某部分…

MATLAB离线文档安装

MATLAB离线文档安装 来源于最全matlab安装离线文档教程只是对内容进行了精简&#xff0c;同时更方便查找 一、下载离线文档 我上传的2023b离线文档 提供本体属于违规行为&#xff0c;本体下载链接已删除 为方便已安装好软件的朋友想安装离线帮助文档&#xff0c;由于官网下载…

模型 IPO(输入、处理、输出)学习模型

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。信息转化与传递。 1 模型 IPO(输入、处理、输出)学习模型的应用 1.1 项目管理知识体系 PMBOK 中的IPO应用 在项目管理领域&#xff0c;PMBOK&#xff08;Project Management Body of Know…

究极小白如何自己搭建一个自动发卡网站-独角数卡

本人从来没接触过建站&#xff0c;我之前都是在TB上花90叫别人给我搭建的网站&#xff0c;前几天这个TB店倒闭跑路了&#xff0c;而我的发卡网也打不开了&#xff0c;没办法&#xff0c;逼上梁山&#xff0c;自己捣鼓出来了&#xff01;下面是2023/4/2自己建好的&#xff01; …

STM32F1 - 系统时钟SysTick

SysTick 1> SysTick硬件框图2> SysTick的时钟源3> 1ms定时_中断方式4> 思考&#xff1a;无符号数 0 - 255 ?相关资料 1> SysTick硬件框图 SysTick属于Cotex-M3&#xff0c;是CPU外设&#xff1b; SysTick: 位宽24bit&#xff0c; 递减计数&#xff0c;自动重装…

《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)

文章目录 2.1 条件语句&#xff1a;决策的艺术2.1.1 基础知识讲解2.1.2 重点案例&#xff1a;用户角色权限判断实现用户角色权限判断扩展功能实现代码功能扩展&#xff1a;添加或删除用户 2.1.3 拓展案例 1&#xff1a;成绩等级判断实现成绩等级判断功能实现代码扩展功能&#…

【开源图床】使用Typora+PicGo+Github+CDN搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

canal监听binlog记录业务数据的变更;canalAdmin对instance做web配置

概述 平时在开发中会通过logback打印一些开发日志&#xff0c;有时也会需要记录一些业务日志&#xff0c;简单的就直接用log记录一下&#xff0c;但是系统中需要记录日志的地方越来越多时&#xff0c;不能每个地方都写一套log记录&#xff1b; 由于平常用的大多都是mysql&…

Linux进程间通信(三)-----System V消息队列

消息队列的概念及原理 消息队列实际上就是在系统当中创建了一个队列&#xff0c;队列当中的每个成员都是一个数据块&#xff0c;这些数据块都由类型和信息两部分构成&#xff0c;两个互相通信的进程通过某种方式看到同一个消息队列&#xff0c;这两个进程向对方发数据时&#x…

【C++ QT项目2】——高仿安信可串口调试助手

【C QT项目2】——高仿安信可串口调试助手 1. 项目概述2. 项目UI设计3. 串口通信核心代码开发3.1 QSerialPort介绍及示例3.2 扫描系统串口3.3 数据的收发3.4 定时发送&#xff08;QT定时器&#xff09;3.5 HEX显示与发送 4. 串口调试助手功能的优化4.1 串口的实时扫描4.2 获取系…