📅  最后修改于: 2023-12-03 15:40:00.588000             🧑  作者: Mango
在这个问题中,我们需要实现二叉树的后序遍历。所谓后序遍历,就是先遍历左子树,然后遍历右子树,最后遍历根节点。
递归是二叉树遍历的常见解法之一,后序遍历也不例外。递归的过程中,我们先访问左子树,然后访问右子树,最后访问根节点。
以下是递归实现后序遍历的代码:
def postorderTraversal(root):
if not root:
return []
res = []
res += postorderTraversal(root.left)
res += postorderTraversal(root.right)
res.append(root.val)
return res
在这段代码中,我们首先判断了当前节点是否为空。如果为空,则直接返回一个空列表。否则,我们先递归遍历左子树,然后递归遍历右子树,最后将根节点的值加入到结果列表中,并返回结果列表。
递归实现后序遍历的时间复杂度为 $O(n)$,其中 $n$ 是节点数目。不过需要注意的是,递归的过程中可能会占用较多的栈空间,容易导致栈溢出问题。
非递归实现后序遍历的方法与前序和中序遍历类似,使用一个栈来模拟递归的过程。不过,后序遍历的非递归实现相对于前序和中序来说,比较麻烦一些。
以下是非递归实现后序遍历的代码:
def postorderTraversal(root):
if not root:
return []
res = []
stack = []
last_visit = None # 标记上一个访问的节点
while stack or root:
if root:
stack.append(root)
root = root.left
else:
peek = stack[-1]
if peek.right and last_visit != peek.right:
root = peek.right
else:
res.append(peek.val)
last_visit = stack.pop()
return res
在这段代码中,我们首先判断当前节点是否为空。如果为空,则直接返回一个空列表。否则,我们定义两个变量 stack
和 last_visit
。stack
是用来模拟递归的栈,last_visit
则是用来标记上一个访问的节点。在循环中,如果当前节点不为空,就将其入栈,并进入其左子树;否则,取出栈顶元素 peek
,如果 peek
的右子树存在且没有被访问过,则进入其右子树;否则,将 peek
的值加入到结果列表中,并将 peek
从栈中弹出。
非递归实现后序遍历的时间复杂度同样为 $O(n)$,不过需要注意的是最坏情况下,栈的深度可能会达到 $n$,因此空间复杂度为 $O(n)$。
该问题要求实现二叉树的后序遍历。递归是二叉树遍历的常见解法之一,后序遍历也不例外。非递归实现后序遍历的方法与前序和中序遍历类似,但是需要注意它的特殊性质(需要标记上一个访问的节点),以及可能出现的栈溢出问题。该算法的时间复杂度均为 $O(n)$,空间复杂度为 $O(n)$。