遍历二叉树的超强算法(Morris遍历)

Morris遍历是一种二叉树遍历算法,它利用空闲指针将空间复杂度降低到O(1),实现时间复杂度O(N)。该算法通过让底层节点的空闲右指针指向上层节点,实现在不使用额外栈空间的情况下遍历二叉树。在遍历过程中,根据节点是否有左孩子和左子树最右节点的右指针状态,来决定节点的移动方向。
摘要由CSDN通过智能技术生成

题目

给定一棵二叉树的头节点head,完成二叉树的先序、中序、后序遍历。如果二叉树的节点为N,则要求时间复杂度为O(N),额外空间复杂度为O(1)。

Morris遍历的的介绍

Morris遍历的二叉树遍历算法的超强进阶算法,该算法可以将非递归遍历中的空间复杂度降为O(1)。从而能够实现时间复杂度为O(N),空间复杂度为O(1)的精妙算法。普通的递归于非递归的解法,其中都使用了栈的结构,递归方法使用了函数栈,非递归的方法则是自己手动维护了一个栈。两者的额外空间都与树的高度相关,空间复杂度为O(h),h为二叉树的高度。
普通的递归与非递归的解法,都使用了栈,在处理完二叉树的某个节点之后可以回到上层去。

Morris遍历的实质

避免使用栈结构,让下层到上层存在指针,具体的是通过让底层节点指向null的空闲指针指回上层的某个节点,从而完成下层到上层的移动。

空闲指针

某些孩子不存在右孩子节点,那么这个节点的right指针就指向null,我们称之为空闲状态。Morris遍历正是利用了这些空闲指针。

Morris遍历的实现原则

假设当前节点为 cur,初始时cur就是整棵树的头节点,根据以下的标准让cur进行移动

  • 如果cur为空的情况下,则过程停止,否则继续下面的过程。

  • 如果cur无左孩子。则cur向右移动(cur = cur.right)

  • 如果cur存在左孩子,找到cur左子树最右节点,记为mostright

  • 如果mostright的右指针指向空,让其指向cur,cur向左移动(cur = cur.left)
    如果mostright的右指针指向cur,让其指向空,cur向右移动(cur = cur.right)

假设一棵二叉树如图所示,使用该二叉树进行遍历。

图一

  • 初始时,cur来到节点4,此时cur存在左子树,故按原则,找到左子树的最右节点(即节点3),发现节点3的右指针指向空,故让其指向cur。如下图所示,cur左移来到节点2。
    在这里插入图片描述

  • cur来到2时,存在左子树,找到左子树的最右节点(即节点1),发现节点1的左指针是指向空,那么让其指向cur,如下图所示,cu r来到节点1。
    在这里插入图片描述

  • cu r来到节点1时,cur此时不存在左子树,根据标准令cur向右指针方向移动,所以回到了节点2
    在这里插入图片描述

  • cur来到节点2,cur此时存在左子树,找到cur左子树的最右节点,即节点1,发现节点1是指向cur的,根据标准将其指向null树被调整为如下图所示的的样子,根据标准cur向右指针的方向移动,所以cur来到了节点3。
    在这里插入图片描述

  • cur来到了节点3,cur此时不存在左子树,,根据标准令cur 向右指针方向移动,所以cu r来到了4。
    在这里插入图片描述

  • cur节点来到4,此时cur存在左子树,找到cur左子树的最右节点,即节点3,发现节点3的指针是指向cur的,那么让其指向null,根据标准cur向右移动来到节点6,最后结果如下图。
    在这里插入图片描述

  • cur来到节点6,cur此时存在左子树,找到左子树的最右节点,即节点5,发现节点5的右指针是指向空的,那么让其指向cur,根据标准,cur向左移动来到了节点5。
    在这里插入图片描述

  • cur来到节点5,cur不存在左子树,根据标准令cur向右指针移动,故cur移动到了6.
    在这里插入图片描述

  • cur来到节点6,cur存在右左子树,找cur的左子树的最右节点,即节点5,发现节点5的右指针指向cur,那么让其指向空,然后根据标准向右移动到节点7.
    在这里插入图片描述

  • cur来到节点7,此时cur不存在左子树,根据标准向右移动,curl来到null的位置。
    在这里插入图片描述

  • cur为空,过程停止。

  • 以上的所有步骤都是按照我们之前的标准进行移动的,cur依次到达的节点为:4,2,1,2,3,4,6,5,6,7。这个序叫做Morris序。

代码

public static class Node{
   
        public int value
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值