2025/5/12 【二叉树】前中后序迭代遍历 LeetCode144, 94, 145 【√】

代码随想录 

144. 二叉树的前序遍历 - 力扣(LeetCode)

# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []

        stack, result = [root], []
        while stack:
            node = stack.pop()
            result.append(node.val)
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
        return result

94. 二叉树的中序遍历 - 力扣(LeetCode)

中序的写法不能是简单修改前序的迭代写法,前序是遇到一个处理一个。中序是遇到一个,先处理它的左子树的。

# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        stack = []
        result = []
        current = root

        while current or stack:
            while current:
                stack.append(current)
                current = current.left

            node = stack.pop()
            result.append(node.val)
            
            current = node.right
        return result

2025/8/14 👆

卡尔的写法:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        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

145. 二叉树的后序遍历 - 力扣(LeetCode)

方法一:修改先序遍历顺序 + 反转结果 : 简单好写,面试推荐

(1)正常先序是:根 → 左 → 右

(2)改成:根 → 右 → 左

(3)最后把结果反转,就得到了:左 → 右 → 根(即后序)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = rightb
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        stack = []
        result = []
        stack.append(root)
        while len(stack) != 0 :
            cur = stack.pop()
            result.append(cur.val)
            if cur.left:
                stack.append(cur.left)
            if cur.right:
                stack.append(cur.right)
        return result[::-1]

(1)result列表反转的两种方法:

①方法1:切片反转

return result[::-1]

②方法2:原地反转 + 返回

result.reverse()
return result

(2)python中list.reverse()reversed()

list.reverse() 是 列表对象的方法,就地修改(会直接修改原列表的顺序),无返回值。

②reversed() 内置函数,是一个通用的可迭代对象反转器,可以用于任何序列(list, str, tuple, range 等)。

不修改原对象,原始列表不会变;返回的是一个迭代器,通常要用 list() 包一层。

③口诀:

reverse 改原地,reversed 造新地;
reverse 没返回,reversed 要包裹。

 

方法2: 用一个“上一次访问节点”指针控制访问(更标准): 规范,训练思维

这个方式更像是严格模拟递归,需要控制“什么时候访问右子树”和“什么时候访问根节点”。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        result = []
        stack = []
        last_visited = None
        current = root

        while stack or current:
            if current:
                stack.append(current)
                current = current.left
            else:
                peek_node = stack[-1]
                # 如果右子树存在且没有被访问过,就去访问右子树
                if peek_node.right and last_visited != peek_node.right:
                    current = peek_node.right
                else:
                    result.append(peek_node.val)
                    last_visited = stack.pop()
        return result
        

        

后续遍历的迭代新解法:来自代码随想录

是一个控制流精细、逻辑清晰但结构稍复杂的写法

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

 

posted @ 2025-05-12 11:41  axuu  阅读(5)  评论(0)    收藏  举报