本文将记录有关莫里斯算法实现二叉树遍历的相关内容,如果有相关内容的同学欢迎邮件与我联系 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