创作

完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>

3天内不再提示

二叉树的前序遍历非递归实现

算法与数据结构 来源:袁厨的算法小屋 作者:袁厨的算法小屋 2021-05-28 13:59 次阅读

我们之前说了二叉树基础及二叉的几种遍历方式及练习题,今天我们来看一下二叉树的前序遍历非递归实现。

前序遍历的顺序是, 对于树中的某节点,先遍历该节点,然后再遍历其左子树,最后遍历其右子树。

我们先来通过下面这个动画复习一下二叉树的前序遍历。

迭代遍历

我们试想一下,之前我们借助队列帮我们实现二叉树的层序遍历,

那么可不可以,也借助数据结构,帮助我们实现二叉树的前序遍历。

假设我们的二叉树为 [1,2,3]。我们需要对其进行前序遍历。其遍历顺序为

当前节点 1,左孩子 2,右孩子 3。

这里可不可以用栈,帮我们完成前序遍历呢?

栈和队列的那些事

我们都知道栈的特性是先进后出,我们借助栈来帮助我们完成前序遍历的时候。

则需要注意的一点是,我们应该先将右子节点入栈,再将左子节点入栈。

这样出栈时,则会先出左节点,再出右子节点,则能够完成树的前序遍历。

我们用一句话对上图进行总结,当栈不为空时,栈顶元素出栈,如果其右孩子不为空,则右孩子入栈,其左孩子不为空,则左孩子入栈。还有一点需要注意的是,我们和层序遍历一样,需要先将 root 节点进行入栈,然后再执行 while 循环。

看到这里你已经能够自己编写出代码了,不信你去试试。

时间复杂度:O(n) 需要对所有节点遍历一次

空间复杂度:O(n) 栈的开销,平均为 O(logn) 最快情况,即斜二叉树时为 O(n)

参考代码

class Solution {

public List《Integer》 preorderTraversal(TreeNode root) {

List《Integer》 list = new ArrayList《》();

Stack《TreeNode》 stack = new Stack《》();

if (root == null) return list;

stack.push(root);

while (!stack.isEmpty()) {

TreeNode temp = stack.pop();

if (temp.right != null) {

stack.push(temp.right);

}

if (temp.left != null) {

stack.push(temp.left);

}

//这里也可以放到前面

list.add(temp.val);

}

return list;

}

}

Morris

Morris 遍历利用树的左右孩子为空(大量空闲指针),实现空间开销的极限缩减。这个遍历方式,稍微有那么一丢丢难理解,不过结合动图,也就一目了然,下面我们先看动画吧。

看完视频,是不是感觉自己搞懂了,又感觉自己没搞懂,哈哈,咱们继续往下看。

我们之前说的,Morris 遍历利用了树中大量空闲指针的特性,我们需要找到当前节点的左子树中的最右边的叶子节点,将该叶子节点的 right 指向当前节点。例如当前节点为2,其左子树中的最右节点为 9 ,则在 9 节点添加一个 right 指针指向 2。

其实上图中的 Morris 遍历遵循两个原则,我们在动画中也能够得出。

1.当 p1.left == null 时,p1 = p1.right。(这也就是我们为什么要给叶子节点添加 right 指针的原因)

2.如果 p1.left != null,找到 p1 左子树上最右的节点。(也就是我们的 p2 最后停留的位置),此时我们又可以分为两种情况,一种是叶子节点添加 right 指针的情况,一种是去除叶子节点 right 指针的情况。

如果 p2 的 right 指针指向空,让其指向 p1,p1向左移动,即 p1 = p1.left

如果 p2 的 right 指针指向 p1,让其指向空,(为了防止重复执行,则需要去掉 right 指针)p1 向右移动,p1 = p1.right。

这时你可以结合咱们刚才提到的两个原则,再去看一遍动画,并代入规则进行模拟,差不多就能完全搞懂啦。

下面我们来对动画中的内容进行拆解 ,

首先 p1 指向 root节点

p2 = p1.left,下面我们需要通过 p2 找到 p1的左子树中的最右节点。即节点 5,然后将该节点的 right 指针指向 root。并记录 root 节点的值。

向左移动 p1,即 p1 = p1.left

p2 = p1.left ,即节点 4 ,找到 p1 的左子树中的最右叶子节点,也就是 9,并将该节点的 right 指针指向 2。

继续向左移动 p1,即 p1 = p1.left,p2 = p1.left。也就是节点 8。并将该节点的 right 指针指向 p1。

我们发现这一步给前两步是一样的,都是找到叶子节点,将其 right 指针指向 p1,此时我们完成了添加 right 指针的过程,下面我们继续往下看。

我们继续移动 p1 指针,p1 = p1.left。p2 = p.left。此时我们发现 p2 == null,即下图此时我们需要移动 p1, 但是不再是 p1 = p1.left 而是 p1 = p1.right。也就是 4,继续让 p2 = p1.left。此时则为下图这种情况

此时我们发现 p2.right != null 而是指向 4,说明此时我们已经添加过了 right 指针,所以去掉 right 指针,并让 p1 = p1.right

下面则继续移动 p1 ,按照规则继续移动即可,遇到的情况已经在上面做出了举例,所以下面我们就不继续赘述啦,如果还不是特别理解的同学,可以再去看一遍动画加深下印象。时间复杂度 O(n),空间复杂度 O(1)下面我们来看代码吧。

代码

class Solution {

public List《Integer》 preorderTraversal(TreeNode root) {

List《Integer》 list = new ArrayList《》();

if (root == null) {

return list;

}

TreeNode p1 = root; TreeNode p2 = null;

while (p1 != null) {

p2 = p1.left;

if (p2 != null) {

//找到左子树的最右叶子节点

while (p2.right != null && p2.right != p1) {

p2 = p2.right;

}

//添加 right 指针,对应 right 指针为 null 的情况

if (p2.right == null) {

list.add(p1.val);

p2.right = p1;

p1 = p1.left;

continue;

}

//对应 right 指针存在的情况,则去掉 right 指针

p2.right = null;

} else {

list.add(p1.val);

}

//移动 p1

p1 = p1.right;

}

return list;

}

}

原文标题:把二叉树揉碎(二)

文章出处:【微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

  • 二叉树
    +关注

    关注

    0

    文章

    43

    浏览量

    11074
收藏 人收藏

    评论

    相关推荐

    二叉树的最小深度

    遍历顺序上依然是后序遍历(因为要比较递归返回之后的结果),但在处理中间节点的逻辑上,最大深度很容易理....
    的头像 算法与数据结构 发表于 04-28 16:27 464次 阅读

    C语言数据结构:什么是二叉树?

    完全二叉树:完全二叉树是效率很高的数据结构。对于深度为K,有n个节点的二叉树,当且仅当每一个节点都与....
    的头像 C语言编程学习基地 发表于 04-21 16:20 460次 阅读

    如何使用 go 实现红黑树

    二叉查找树也叫二叉搜索树,也叫二叉排序树,它具有以下特点:1. 如果左子树不为空,则左子树上的结点的....
    的头像 Linux爱好者 发表于 03-21 11:54 388次 阅读

    二叉树上应该怎么求

      二叉树上应该怎么求,二叉搜索树上又应该怎么求? 在求众数集合的时候有一个技巧,因为题目中众数是可....
    的头像 算法与数据结构 发表于 11-22 11:32 581次 阅读

    数据结构与算法分析中的二叉树与堆有关知识汇总

    该资料包括数据结构与算法分析中的二叉树与堆有关的一些知识
    发表于 11-03 09:37 139次 阅读

    二叉排序树AVL如何实现动态平衡

      什么是AVL树 大家好,我是bigsai,好久不见,甚是想念,今天给大家讲讲AVL树。 对于树这....
    的头像 算法与数据结构 发表于 10-28 17:02 634次 阅读
    二叉排序树AVL如何实现动态平衡

    算法学习中如何打印二叉树节点

    大家好,我是吴师兄,直接开始今天的算法学习,冲冲冲。 一、题目描述 从上到下打印出二叉树的每个节点,....
    的头像 算法与数据结构 发表于 10-22 09:37 685次 阅读

    如何修剪二叉搜索树

      如果不对递归有深刻的理解,本题有点难。单纯移除一个节点那还不够,要修剪! 669. 修剪二叉搜索....
    的头像 算法与数据结构 发表于 10-11 14:16 613次 阅读

    C++基础语法中的二叉树详解

    本期是C++基础语法分享的第十四节,今天给大家来梳理一下树!   二叉树 BinaryTree.cp....
    的头像 C语言编程学习基地 发表于 09-29 18:02 1109次 阅读

    如何才能够翻转二叉树

    这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。 但正是因为这道题太简单,一看就会,一....
    的头像 新材料在线 发表于 09-01 11:45 924次 阅读

    C语言编程中如何求出二叉树后序遍历

    题目 已知二叉树前序为 ABDFGCEH 后序序列为 BFDGACEH ,要求输出后序遍历为 FGD....
    的头像 C语言编程基础 发表于 08-23 11:04 2844次 阅读

    二叉树的所有路径介绍

    以为只用了递归,其实还用了回溯 257. 二叉树的所有路径 题目地址:https://leetcod....
    的头像 新材料在线 发表于 08-13 17:51 1489次 阅读
    二叉树的所有路径介绍

    面试官考点之索引是什么?

    可以从几个维度去看这个问题,查询是否够快,效率是否稳定,存储数据多少,以及查找磁盘次数等等。为什么不....
    的头像 数据分析与开发 发表于 03-05 10:37 1109次 阅读
    面试官考点之索引是什么?

    建立决策树的逻辑

    像上面的这样的二叉树状决策在我们生活中很常见,而这样的选择方法就是决策树。机器学习的方法就是通过平时....
    的头像 深度学习自然语言处理 发表于 10-10 10:44 1544次 阅读
    建立决策树的逻辑

    Max Howell因为不会翻转一棵二叉树,被Google拒绝

    Max Howell 就是 Homebrew 的创作者,也是一名业内知名的 MacOS / iOS ....
    的头像 算法与数据结构 发表于 09-03 10:52 9832次 阅读

    Offer系列面试题0:重建二叉树

    以本题的序列为例,前序遍历序列的第一个数字 3 就是根结点的值,在中序遍历序列,找到根结点值的位置。....
    的头像 算法与数据结构 发表于 07-09 15:03 930次 阅读
    Offer系列面试题0:重建二叉树

    红黑树(Red Black Tree)是一种自平衡的二叉搜索树

    平衡(Balance):就是当结点数量固定时,左右子树的高度越接近,这棵二叉树越平衡(高度越低)。而....
    的头像 算法与数据结构 发表于 07-01 15:05 1695次 阅读
    红黑树(Red Black Tree)是一种自平衡的二叉搜索树

    删除二叉搜索树中的节点

    因为是二叉搜索树,对于树上每个节点来说,其 右子树的节点都要大于其左子树的节点 ,那么要找对应节点,....
    的头像 算法与数据结构 发表于 06-23 10:33 2027次 阅读
    删除二叉搜索树中的节点

    一个数据结构-线段树

    对于求区间和的问题,前缀和数组 是一个不错的选择,构建好前缀和数组后,求一个区间和的话只要前后一减就....
    的头像 算法与数据结构 发表于 05-06 11:02 2180次 阅读
    一个数据结构-线段树

    面试二叉树看这11个就够了

    根据前、中序遍历的特点,(根左右、左根右),先根据前序遍历确定根节点,然后在中序遍历知道该根节点的左....
    的头像 算法与数据结构 发表于 11-27 16:25 2650次 阅读

    面试算法之重建二叉树

    那么问题来了,只知道前序遍历能不能反推二叉树呢?我们就试一下,比如题目中所述,{1,2,4,7,3,....
    的头像 算法与数据结构 发表于 11-27 15:59 1838次 阅读

    一份用Python代码实现算法的资源帖,涵盖从入门到高级的各类算法

    在这个项目中并不是对所有内容都进行了详细介绍,有部分主题的代码非常丰富。为了帮助大家高效地利用这一学....
    的头像 city_prolove 发表于 05-11 10:30 2165次 阅读
    一份用Python代码实现算法的资源帖,涵盖从入门到高级的各类算法

    二叉树,一种基础的数据结构类型

    然后我们再定义一棵深度也为 3 的二叉树,该二叉树的 n 个结点(n≤7),当从 1 到 n 的每个....
    的头像 人工智能头条 发表于 04-13 10:48 3099次 阅读
    二叉树,一种基础的数据结构类型

    数据结构与算法:图的遍历过程中,搜索方法的不同

    图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶....
    的头像 city_prolove 发表于 04-04 16:40 2763次 阅读
    数据结构与算法:图的遍历过程中,搜索方法的不同

    普及一下程序猿们经常遇见的树

    趁着这个植树节,普及一下程序猿们经常遇见的树。B树的插入会发生结点的分裂操作。当插入操作引起了 s ....
    的头像 city_prolove 发表于 03-13 09:31 2235次 阅读

    基于二叉树的ensemble异常检测算法

    xi样本点的isolation需要大概12次划分,而异常点x0指需要4次左右。因此,我们可以根据划分....
    的头像 人工智能爱好者社区 发表于 12-11 16:57 3027次 阅读
    基于二叉树的ensemble异常检测算法

    4中二叉树的遍历方式介绍

    对于一种数据结构而言,遍历是常见操作。二叉树是一种基本的数据结构,是一种每个节点的儿子数目都不多于2....
    的头像 人工智能爱好者社区 发表于 04-27 17:23 3857次 阅读
    4中二叉树的遍历方式介绍

    B-Tree与二叉查找树的对比

    从前面分析情况来看,减少磁盘IO的次数就必须要压缩树的高度,让瘦高的树尽量变成矮胖的树,所以B-Tr....
    的头像 Linux阅码场 发表于 04-15 10:54 7850次 阅读
    B-Tree与二叉查找树的对比

    关于二叉树一些数据结构和算法相关的题目

    最近总结了一些数据结构和算法相关的题目,这是第一篇文章,关于二叉树的。
    的头像 算法与数据结构 发表于 02-07 13:57 2473次 阅读

    一文详解红黑树

    红黑树是一种自平衡的二叉查找树,是一种高效的查找树。它是由 Rudolf Bayer 于1972年发....
    的头像 算法与数据结构 发表于 02-02 17:25 3518次 阅读
    一文详解红黑树

    熵的二叉树多类支持向量机的漏洞分类

    为了有效提高漏洞分类的准确性,针对基于二叉树多类支持向量机分类算法的分类复杂性和分类结果依赖二叉树的....
    发表于 01-25 10:40 643次 阅读

    AVL 树和普通的二叉查找树的详细区别分析

    那 AVL 树和普通的二叉查找树有何区别呢?如图,如果我们插入的是一组有序上升或下降的数据,则一棵普....
    的头像 算法与数据结构 发表于 01-15 14:36 4267次 阅读
     AVL 树和普通的二叉查找树的详细区别分析

    基于二叉树的多用户ORAM改进方案

    随着大数据及数据挖掘技术的发展,云计算环境中用户访问模式成为泄露用户隐私的一条途径.不经意随机存取技....
    发表于 01-13 11:05 417次 阅读

    基于二叉树的算术编码二值化方法

    在算术编码研究中,待编码的语法元素需要采用何种二值化方法以及二值化后每个比特的概率模型选择是算术编码....
    发表于 01-03 16:53 471次 阅读

    基于二叉树的电子系统故障诊断专家系统

    在分析专家系统发展及其在电子系统故障诊断中应用状况的基础上,针对当前装甲装备电子系统故障诊断中先进的....
    发表于 12-13 14:51 528次 阅读
    基于二叉树的电子系统故障诊断专家系统

    二叉树层次遍历算法的验证

    实现二叉树的层次遍历算法,并对用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,....
    发表于 11-28 01:05 1351次 阅读
    二叉树层次遍历算法的验证

    二叉树的前序遍历、中序遍历、后续遍历的非递归实现

    前序遍历:先访问该节点,然后访问该节点的左子树和右子树; 中序遍历:先访问该节点的左子树,然后访问....
    发表于 11-27 11:24 738次 阅读

    二叉树基本操作课程设计

    课程设计
    发表于 10-12 08:50 408次 阅读

    二叉树实验报告_数据结构

    发表于 06-25 16:19 510次 阅读

    基于二叉树的时序电路测试序列设计

    为了实现时序电路状态验证和故障检测,需要事先设计一个输入测试序列。基于二叉树节点和树枝的特性,建立时....
    发表于 07-12 13:57 621次 阅读
    基于二叉树的时序电路测试序列设计

    基于二叉树满足MC DC测试用例设计方法

    软件测试是保证软件质量的有效方法,但测试工作过程繁琐,工作量较多。探索高效、可靠的测试用例设计方法一....
    发表于 03-01 16:22 610次 阅读

    二叉树算法在单总线上的C51 软件实现The Impleme

    单总线技术是一种新技术,由于所有的单总线器件均并联在一条信号线上,其信号传输较慢,主要应用于低速测控....
    发表于 06-01 11:20 444次 阅读