二叉树后序遍历相较于前序和中序要相对复杂一些,主要原因在于,前序遍历只需特别关注根结点,中序遍历需要额外考虑左结点,而后序遍历不仅要记录左结点,根结点还需不断注意是否有右结点。出现这一变化的原因是后序遍历左右根遍历的特点。
示例1:
同样附上递归和迭代两种方法,需要着重注意迭代的过程。
代码:
递归法:
class Solution:
def postorderTraversal(self, root):
if root is None:
return []
return self.postorderTraversal(root.left) + self.postorderTraversal(root.right) + [root.val]
迭代法:
class Solution:
def postorderTraversal(self, root):
stack = []
result = []
while root or stack:
while root:
stack.append(root)
root = root.left
temp = stack[-1].right
if temp:
root = temp
else:
temp = stack.pop()
result.append(temp.val)
while stack and temp == stack[-1].right:
temp = stack.pop()
result.append(temp.val)
return result
代码说明:
(1) while root:
stack.append(root)
root = root.left
这几步仍是将所有左子树的左结点压入栈中。
(2) temp = stack[-1].right
当无左子树左结点时,要记录最后一个左结点的右结点,即栈顶元素的右结点。
(3) if temp:
root = temp
如果此时最后一个左结点有右孩子,则需把右孩子也压入栈中。
else:
temp = stack.pop()
result.append(temp.val)
否则说明该栈顶元素为一个根节点,已无左右孩子,只需弹出自己。
(4) while stack and temp == stack[-1].right:
temp = stack.pop()
result.append(temp.val)
这个循环表示:弹出了栈顶结点后需要判断已弹出的这个结点是否为现在栈顶元素的右孩子。若是,表明当前栈顶元素也已无左右孩子,可以弹出。否则说明当前栈顶元素还存在右孩子 需要对其右孩子进行处理。