【二叉树进阶】--- 前中后序遍历非递归

news2024/9/27 15:21:20

 Welcome to 9ilk's Code World

       

(๑•́ ₃ •̀๑) 个人主页:       9ilk

(๑•́ ₃ •̀๑) 文章专栏:     算法Journey 


本篇博客我们将来了解有关二叉树前中后序遍历的非递归版本。


🏠 前序遍历

要迭代非递归实现二叉树的前序遍历,首先还是要借助递归的类似思想,只需要把结点存在栈中,方便类似递归回退时取出父路径结点。跟这里不同的是,我们把一颗二叉树分为两个部分:1. 左路结点 2. 左路结点的右子树。

  • 我们先访问左路结点将他们依次入栈,再依次访问左路结点的右子树。
  • 访问左路结点的右子树只需要我们从栈里面取出左路结点,由于右子树又可以分为左路结点和右子树,所以我们以循环子问题的思想访问左路结点的右子树。

参考代码:

class Solution {
public:
    vector<int> ret;
    vector<int> preorderTraversal(TreeNode* root)
    {
         TreeNode* cur = root;
         stack<TreeNode*> st;
         while(cur || !st.empty())
         {
                //访问左路节点
             while(cur)   
             {
               st.push(cur);
               ret.push_back(cur->val)
               cur = cur->left;
             }
            //从栈中取左路节点依次访问他们右子树
            TreeNode* top = st.top();
          
            st.pop();
            cur = top->right;    
         }
       return ret;            
    }
};

🏠 中序遍历

中序跟前序其实思路完全一致,只是访问根的时机不同。中序是对左路结点时不能先访问,而是先依次入栈,入栈完左路结点后再访问这些左路结点,再依次访问他们各自的右子树。

参考代码:

class Solution {
public:
  vector<int> ret;

    vector<int> inorderTraversal(TreeNode* root) 
    {
         TreeNode* cur = root;
         stack<TreeNode*> st;
         while(cur || !st.empty())
         {
                //访问左路节点
             while(cur)   
             {
               st.push(cur); //先入栈不访问
               cur = cur->left;
             }
            TreeNode* top = st.top();
            ret.push_back(top->val);//访问
            st.pop();
            cur = top->right;    //访问右子树
         }
       return ret;     
    }
};

🏠 后序遍历

后序跟前序的思路也是完全一致,毕竟模拟的是递归展开过程,只不过后序是左子树-右子树-根,最后再访问根结点,也就是说要左右子树都访问完之后才能访问根并出栈。

TreeNode* top = st.top();
if(top->right == nullptr)
{
   ret.push_back(top->val);
   st.pop();
}
else //访问右子树
{
  cur = top->right;
}

当我们还面临一个问题当取到左路结点的右子树时,我们需要想办法标记判断右子树是否已经访问过了,如果访问过就直接访问根,没有访问过就访问右子树。因此我们上述逻辑访问右子树时不知道是否已经访问过右子树,处理完右子树后上一层的结点没有pop掉再次判断,因此会陷入循环。

解决方法是用一个prev变量来记录上一个访问的结点。但我们需要明白以下逻辑:

1. 取到一个左路结点时左子树已经访问过了

2.如果左路节点右子树不为空,右子树没有访问,那么上一个访问节点是左子树的根,此时需要访问右子树。

3.如果左路节点右子树不为空,右子树已经访问过,那么上一个访问节点应该是右子树的根,此时需要访问根

4.如果左路节点右子树为空,此时说明左子树已经访问,右子树不需要访问,此时需要访问根。

参考代码:

class Solution {
public:
    vector<int> ret;
    vector<int> postorderTraversal(TreeNode* root) 
    {
         TreeNode* cur = root;
         stack<TreeNode*> st;
         TreeNode* pre = nullptr;
         while(cur || !st.empty())
         {
                //访问左路节点
             while(cur)   
             {
               st.push(cur);
               cur = cur->left;
             }
            // 这时代表左子树已经访问过了
            TreeNode* top = st.top();
            if(top->right == nullptr || top->right == pre)右子树为空或右子树已经访问完才访问根
            {
                ret.push_back(top->val);
                st.pop();   
                pre = top;
            }
            else
            cur = top->right;    //右子树没访问再循环子问题访问右子树
         }
       return ret;     
    }
};

完。

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

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

相关文章

【pgAdmin4】创建/删除:数据库Database和数据库表Table

目录 0.环境 1.简介 2.详细步骤 1&#xff09;创建数据库 法一&#xff1a;UI界面创建 法二&#xff1a;sql语句创建数据库 2&#xff09;创建数据库表 查看数据库表 查看数据库表内容 法一&#xff1a;UI界面创建数据库表 法二&#xff1a;sql语句创建数据库表 3&…

C_09_字符操作

字符串相关函数 头文件都是 string.h 概述&#xff1a; 由系统提供的由字符串处理的函数 属于库函数 所属头文件 string.h 1 strlen 测量字符串长度 语法&#xff1a; size_t strlen(const char *s);参数&#xff1a;要测量的字符串返回值&#xff1a;长度注意:测量的长度…

Screenshot Software,截屏软件

一.截屏软件 1.1 自带的一些截屏软件 &#xff08;1&#xff09;微信 &#xff08;2&#xff09;QQ 有一次无意中测试了下&#xff0c;截屏软件的截屏质量&#xff0c;发现对于同一个页面截全屏&#xff0c;微信截的屏质量相对于 win 自带的截图软件还要好的&#xff0c;所以…

Elasticsearch 开放推理 API 增加了对 Anthropic 的 Claude 的支持

作者&#xff1a;来自 Elastic Jonathan Buttner 我们很高兴地宣布 Elasticsearch Open Inference API 的最新功能&#xff1a;集成 Anthropic 的 Claude。这项功能使 Elastic 用户能够直接连接到 Anthropic 平台&#xff0c;并使用 Claude 3.5 Sonnet 等大型语言模型来构建 Ge…

Java 应用服务器有哪些?

应用服务器 Java 应用服务器是专门用来运行基于Java技术的Web应用程序的服务器。 这些服务器支持Java EE&#xff08;Java Platform, Enterprise Edition&#xff09;规范&#xff0c;提供了多种服务&#xff0c;如事务管理、Java Naming and Directory Interface (JNDI)、数…

机器之心 | 五倍吞吐量,性能全面包围Transformer:新架构Mamba引爆AI圈

本文来源公众号“机器之心”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;五倍吞吐量&#xff0c;性能全面包围Transformer&#xff1a;新架构Mamba引爆AI圈 屹立不倒的 Transformer 迎来了一个强劲竞争者。 在别的领域&#xff…

探索 HarmonyOS NEXT Developer Beta6,开启创新应用

华为的鸿蒙 NEXT 的发展越来越快 HarmonyOS NEXT Developer Beta6 版本的推出&#xff0c;为开发者们带来了全新的机遇和挑战。这个版本不仅拥有诸多令人振奋的新特性&#xff0c;还提供了丰富的新增资源和精彩的开发者活动。 新特性方面&#xff0c;DevEco Studio NEXT Dev…

算法练习题06:leetcode793每日温度

单调栈解法 class Solution {public int[] dailyTemperatures(int[] temperatures) {int length temperatures.length;int[] ans new int[length];Stack<Integer> stack new Stack<>();for(int i 0;i<length;i){int temperature temperatures[i];while(!…

系统功能性能优化:从问题定位到解决方案的系统性分析

引言 在现代软件系统中&#xff0c;性能优化是确保系统稳定、响应迅速和资源高效利用的关键。面对复杂的系统架构和业务逻辑&#xff0c;进行性能优化往往需要遵循一系列系统性的步骤&#xff0c;以确保问题被准确识别&#xff0c;解决方案被有效实施。以下是一套专业的系统功…

Linux下的使用字符设备驱动框架编写ADC驱动 ——MQ-4传感器

ADC的原理 ADC 的作用&#xff1a;模拟信号转换为数字信号 模拟信号一般是指连续变化的电压信号&#xff0c;其数值在一定范围内变化。 而数字信号是由一系列离散的数字表示&#xff0c; 只能取有限的值&#xff0c;通常以二进制形式表示。 ADC通常由一个采样保持电路、一个…

C++(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例2

C(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例2 文章目录 C(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例21、概述2、实现效果3、主要代码4、源码地址 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;GIS开发 &#x1f448; 1、概述 支持多线程…

Android 事件分发:为什么有时候会出现事件冲突?事件的顺序是如何的?出现事件冲突如何解决呢?比如为什么左右可以滑动,而上下却不行?

目录&#xff1a; 一、为什么要学习事件呢&#xff1f; 1.在开发复杂的应用时&#xff0c;经常需要处理复杂的用户交互逻辑。学习事件分发机制可以帮助你更好地控制事件的传递和处理流程&#xff0c;从而解决一些复杂的交互问题&#xff0c;如滑动冲突、点击穿透等。 2.面试需…

NLP笔记:BLEU

1 介绍 bleu是一种文本评估算法&#xff0c;它是用来评估机器翻译跟专业人工翻译之间的对应关系核心思想就是机器翻译越接近专业人工翻译&#xff0c;质量就越好&#xff0c;经过bleu算法得出的分数可以作为机器翻译质量的一个指标 2 BLEU原理 2.1 N-gram BLEU采用了N-gram…

NLP(三):词向量

自然语言处理&#xff0c;处理的是自然的需要&#xff0c;通过分词后得到我们想要的词&#xff0c;但是不可能直接把这种自然语言传递给计算机来理解。这时候就有一个概念叫词向量&#xff0c;用来表示词的特征向量或表征。 一&#xff0c;词向量的表示 词向量的表示主要有两…

C——四种排序方法

这一篇文章我将要详细讲解四种排序方法 1.冒泡排序 冒泡排序是我们首先接触的排序方法&#xff0c;他通过两次循环完成。 /*冒泡排序*/&#xff08;升序&#xff09; void maopao(int *a,int n) {int i;for(i 0; i < n-1; i){for (int j 0; j < n - 1 - i; j){if (a[…

mars3D使用 POI 查询、限定范围

mars3D使用 一、mars3D中使用 geocoder 进行 POI 查询二、限定范围1.初始化时渲染2.重新渲染 总结 一、mars3D中使用 geocoder 进行 POI 查询 在json文件或者自己的mapOptions中配置token "token":{"tianditu":"e5c3984ced09bc1f55e8e1107fdc5a6b&q…

论文速览【LLM-agent】—— 【ReAct】Synergizing Reasoning and Acting in Language Models

文章链接&#xff1a;ReAct: Synergizing Reasoning and Acting in Language Models发表&#xff1a;ICLR 2023领域&#xff1a;LLM agent 摘要&#xff1a;尽管大型语言模型&#xff08;LLMs&#xff09;在语言理解和交互式决策任务中展示了令人印象深刻的能力&#xff0c;但它…

正弦波振荡器工作原理及频率稳定性条件

晶发电子专注17年晶振生产,晶振产品包括石英晶体谐振器、振荡器、贴片晶振、32.768Khz时钟晶振、有源晶振、无源晶振等&#xff0c;产品性能稳定,品质过硬,价格好,交期快.国产晶振品牌您值得信赖的晶振供应商。 正弦波振荡器是一种能够自动将直流电转换为特定频率和振幅的正弦交…

解析云原生架构中两大核心原则

1.云原生架构是什么 云原生架构是一种设计和构建应用程序的现代方法&#xff0c;以微服务、容器化、持续集成和持续部署&#xff08;CI/CD&#xff09;等技术为基础&#xff0c;使应用能够在云环境中动态运行。云原生架构强调解耦合、弹性和自动化&#xff0c;开发团队在独立的…

【高级编程】万字整理集合框架 迭代器 泛型(含方法案例)

文章目录 集合框架集合接口集合类ArrayListLinkedListHashSet 迭代器 IteratorMap 接口泛型Collections 工具类 集合框架 如果并不知道程序运行时会需要多少对象&#xff0c;或者需要更复杂方式存储对象——可以使用Java集合框架 Java集合框架提供了一套性能优良、使用方便的…