莫里斯算法实现二叉树的中序、前序、后序遍历,python实现

本文介绍了莫里斯算法在二叉树遍历中的应用,包括Python和Java实现。通过改变二叉树结构,算法实现了空间复杂度为O(1)的中序、前序、后序遍历,同时讨论了递归和迭代法的空间复杂度问题。
摘要由CSDN通过智能技术生成

本文将记录有关莫里斯算法实现二叉树遍历的相关内容,如果有相关内容的同学欢迎邮件与我联系 zhaoliang19960421@outlook.com

相关内容

在二叉树遍历中,递归法需要O(N)的空间复杂度,因为递归的时候需要把当前的路径记录下来直到结束;迭代法需要O(N)的空间复杂度,因为需要一个堆栈记录从高层节点到底层叶子节点的路径,然后在以此退栈,实现从底层叶子到高层节点,然后再向另一个方向的遍历(以前序为例,前序遍历,中左右,需要从中的高层根按照左子树走到左子树的叶子结点,然后利用堆栈在回到根节点,然后在访问根节点,然后在按照右子树走到右子树的叶子结点,实现左中右的访问顺序),所以需要的堆栈的空间大小就是树的高度,在最差的情况下就是节点个数N。

递归法和迭代法的时间复杂度都是O(n),因为每个节点都需要被访问起码一次,迭代法需要被访问两次,但是仍然是常数级的,仍然是O(N)的时间复杂度。

而莫里斯算法实现了时间复杂度O(N),但是空间复杂度O(1)的中、前、后序遍历。

莫里斯算法的核心思路是给每一个根节点找到他的中序前驱节点(左子树的最右的叶子),该中序前驱节点的右子树本来为空,利用这个空的内存指向根节点,作为从左子树回到根节点的方式,这么做就不需要堆栈来记录从根节点到叶子节点的顺序来返回了。

对于根节点而已设置了指向他的中序前驱节点的右子树之后,每个根节点会被访问两次,第一次访问时候是找到中序前驱节点然后设置空内存,第二次访问是利用中序前驱节点的右子树指向了根,这个时候根节点是第二次被访问,这个时候去找根节点的中序前驱节点的右子树,这个时候中序前驱的右子树已经指向了根节点,那么这个时候就需要将右子树值为空,重新回到原始的样子。

不同的遍历方式决定跟节点在第几次访问的时候被输出(后序除外)。
以下是具体的python代码

	'''
	莫里斯算法中序遍历
	莫里斯算法是将每个节点的中序的前驱节点的空右子树的空内存
	(左子树的最右叶子节点的空右子树的空右子树的空内存)指向该节点,
	作为从中序前驱节点返回上一层的途径。
	和之前的迭代法相比较,迭代法需要一个堆栈依次记录从上层到下层的记录,
	当到达最低层的节点时通过出栈的方式获得上层节点。
	而莫里斯算法,利用之前设置的空内存从底层节点返回上层节点。
	'''
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        current = root  # 当前的节点,从根节点开始
        while current:
        	# 如果当前节点没有左子树,那么就输出该节点,并且转到右子树上
        	# 因为,中序遍历,左中右,没有了左子树之后,就输出中,然后转到右子树
            if not current.left:  
                result.append(current.val)
                current = current
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值