diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index ba63d06b..a3c5b38f 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -240,14 +240,14 @@ class Solution { # 前序遍历-迭代-LC144_二叉树的前序遍历 class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: - # 根结点为空则返回空列表 + # 根节点为空则返回空列表 if not root: return [] stack = [root] result = [] while stack: node = stack.pop() - # 中结点先处理 + # 中节点先处理 result.append(node.val) # 右孩子先入栈 if node.right: @@ -262,19 +262,23 @@ class Solution: # 中序遍历-迭代-LC94_二叉树的中序遍历 class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: - stack = [] # 不能提前将root结点加入stack中 + + if not root: + return [] + stack = [] # 不能提前将root节点加入stack中 + result = [] cur = root while cur or stack: - # 先迭代访问最底层的左子树结点 + # 先迭代访问最底层的左子树节点 if cur: stack.append(cur) cur = cur.left - # 到达最左结点后处理栈顶结点 + # 到达最左节点后处理栈顶节点 else: cur = stack.pop() result.append(cur.val) - # 取栈顶元素右结点 + # 取栈顶元素右节点 cur = cur.right return result ``` @@ -289,7 +293,7 @@ class Solution: result = [] while stack: node = stack.pop() - # 中结点先处理 + # 中节点先处理 result.append(node.val) # 左孩子先入栈 if node.left: @@ -301,6 +305,44 @@ class Solution: return result[::-1] ``` +#### Python 后序遍历的迭代新解法: +* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。这个实现方法在面试中不容易写出来,在下一节,我将改造本代码,奉上代码更简洁、更套路化、更容易实现的统一方法。 + +```python +class Solution: + def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: + values = [] + stack = [] + popped_nodes = set() # 记录值已经被收割了的 nodes,这是关键,已经被收割的节点还在树中,还会被访问到,但逻辑上已经等同于 null 节点。 + current = root + + while current or stack: + if current: # 一次处理完一个节点和他的左右儿子节点,不处理孙子节点,孙子节点由左右儿子等会分别处理。 + stack.append(current) # 入栈自己 + + if current.right: + stack.append(current.right) # 入栈右儿子 + + if current.left: # 因为栈是后进先出,后序是‘左右中’,所以后加左儿子 + stack.append(current.left) # 入栈左儿子 + + current = None # 会导致后面A处出栈 + continue + + node = stack.pop() # A处,出的是左儿子,如果无左儿子,出的就是右儿子,如果连右儿子也没有,出的就是自己了。 + + # 如果 node 是叶子节点,就可以收割了;如果左右儿子都已经被收割了,也可以收割 + if (node.left is None or node.left in popped_nodes) and \ + (node.right is None or node.right in popped_nodes): + popped_nodes.add(node) + values.append(node.val) + continue + + current = node # 不符合收割条件,说明 node 下还有未入栈的儿子,就去入栈 + + return values +``` + ### Go: > 迭代法前序遍历