2026/4/18 11:39:38
网站建设
项目流程
做软件贵还是做网站贵,网站建设|,网站风格的设计原则,装修公司做网站的好处一、二叉树基础与遍历概述1.1 二叉树结构定义pythonclass TreeNode:二叉树节点定义def __init__(self, val0, leftNone, rightNone):self.val val # 节点值self.left left # 左子节点self.right right # 右子节点1.2 遍历方式…一、二叉树基础与遍历概述1.1 二叉树结构定义pythonclass TreeNode: 二叉树节点定义 def __init__(self, val0, leftNone, rightNone): self.val val # 节点值 self.left left # 左子节点 self.right right # 右子节点1.2 遍历方式分类text二叉树遍历 ├── 深度优先遍历 (DFS) │ ├── 前序遍历 (Preorder) │ ├── 中序遍历 (Inorder) │ └── 后序遍历 (Postorder) └── 广度优先遍历 (BFS) └── 层序遍历 (Levelorder)二、递归遍历最直观的实现2.1 前序遍历根-左-右遍历顺序先访问根节点然后左子树最后右子树pythondef preorder_traversal_recursive(root): 前序遍历 - 递归版本 result [] def dfs(node): if not node: return result.append(node.val) # 访问根节点 dfs(node.left) # 遍历左子树 dfs(node.right) # 遍历右子树 dfs(root) return result图解前序遍历text1 / \ 2 3 / \ \ 4 5 6 前序遍历顺序1 → 2 → 4 → 5 → 3 → 6 访问路径根(1) → 左(2) → 左(4) → 右(5) → 右(3) → 右(6)2.2 中序遍历左-根-右遍历顺序先访问左子树然后根节点最后右子树pythondef inorder_traversal_recursive(root): 中序遍历 - 递归版本 result [] def dfs(node): if not node: return dfs(node.left) # 遍历左子树 result.append(node.val) # 访问根节点 dfs(node.right) # 遍历右子树 dfs(root) return result图解中序遍历text1 / \ 2 3 / \ \ 4 5 6 中序遍历顺序4 → 2 → 5 → 1 → 3 → 6 访问路径左(4) → 根(2) → 右(5) → 根(1) → 左(3) → 右(6)2.3 后序遍历左-右-根遍历顺序先访问左子树然后右子树最后根节点pythondef postorder_traversal_recursive(root): 后序遍历 - 递归版本 result [] def dfs(node): if not node: return dfs(node.left) # 遍历左子树 dfs(node.right) # 遍历右子树 result.append(node.val) # 访问根节点 dfs(root) return result图解后序遍历text1 / \ 2 3 / \ \ 4 5 6 后序遍历顺序4 → 5 → 2 → 6 → 3 → 1 访问路径左(4) → 右(5) → 根(2) → 右(6) → 左(3) → 根(1)2.4 统一递归模板pythondef tree_traversal_recursive(root, orderpreorder): 统一递归遍历模板 result [] def dfs(node): if not node: return if order preorder: result.append(node.val) # 前序根左右 dfs(node.left) # 遍历左子树 if order inorder: result.append(node.val) # 中序左根右 dfs(node.right) # 遍历右子树 if order postorder: result.append(node.val) # 后序左右根 dfs(root) return result三、迭代遍历栈模拟递归3.1 前序遍历迭代实现pythondef preorder_traversal_iterative(root): 前序遍历 - 迭代版本使用栈 if not root: return [] result [] stack [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算法流程图示text初始stack [1], result [] 步骤1弹出1访问1压入3压入2 stack [3, 2], result [1] 步骤2弹出2访问2压入5压入4 stack [3, 5, 4], result [1, 2] 步骤3弹出4访问4 stack [3, 5], result [1, 2, 4] 步骤4弹出5访问5 stack [3], result [1, 2, 4, 5] 步骤5弹出3访问3压入6 stack [6], result [1, 2, 4, 5, 3] 步骤6弹出6访问6 stack [], result [1, 2, 4, 5, 3, 6]3.2 中序遍历迭代实现pythondef inorder_traversal_iterative(root): 中序遍历 - 迭代版本 result [] stack [] current root while current or stack: # 一直向左走到尽头 while current: stack.append(current) current current.left # 弹出节点并访问 current stack.pop() result.append(current.val) # 转向右子树 current current.right return result算法流程图示text初始current 1, stack [] 步骤1向左走到尽头1入栈2入栈4入栈 stack [1, 2, 4], current None 步骤2弹出4访问4current 4.right None result [4], stack [1, 2] 步骤3弹出2访问2current 2.right 5 result [4, 2], stack [1] 步骤45入栈current None stack [1, 5] 步骤5弹出5访问5current 5.right None result [4, 2, 5], stack [1] 步骤6弹出1访问1current 1.right 3 result [4, 2, 5, 1], stack [] 步骤73入栈6入栈current None stack [3, 6] 步骤8弹出6访问6current None result [4, 2, 5, 1, 6], stack [3] 步骤9弹出3访问3current None result [4, 2, 5, 1, 6, 3], stack []3.3 后序遍历迭代实现pythondef postorder_traversal_iterative(root): 后序遍历 - 迭代版本双栈法 if not root: return [] result [] stack1 [root] # 用于遍历 stack2 [] # 用于反转顺序 while stack1: node stack1.pop() stack2.append(node) # 左子树先入栈1保证在stack2中右子树在左子树前面 if node.left: stack1.append(node.left) if node.right: stack1.append(node.right) # 将stack2中的节点弹出即为后序遍历 while stack2: result.append(stack2.pop().val) return result单栈实现后序遍历pythondef postorder_traversal_iterative_single_stack(root): 后序遍历 - 单栈实现 if not root: return [] result [] stack [] last_visited None # 记录上次访问的节点 current root while stack or current: # 向左走到尽头 while current: stack.append(current) current current.left # 查看栈顶节点 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 result3.4 统一迭代模板标记法pythondef tree_traversal_iterative_unified(root, orderpreorder): 统一迭代遍历模板标记法 if not root: return [] result [] stack [(root, False)] # (节点, 是否已访问) while stack: node, visited stack.pop() if not node: continue if visited: result.append(node.val) else: # 根据遍历顺序调整入栈顺序 if order preorder: # 根左右 stack.append((node.right, False)) stack.append((node.left, False)) stack.append((node, True)) elif order inorder: # 左根右 stack.append((node.right, False)) stack.append((node, True)) stack.append((node.left, False)) elif order postorder: # 左右根 stack.append((node, True)) stack.append((node.right, False)) stack.append((node.left, False)) return result四、层序遍历BFS4.1 基础层序遍历pythonfrom collections import deque def level_order_traversal(root): 层序遍历 - 基础版 if not root: return [] result [] queue deque([root]) # 使用队列 while queue: level_size len(queue) level_nodes [] for _ in range(level_size): node queue.popleft() level_nodes.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_nodes) return result图解层序遍历text1 / \ 2 3 / \ \ 4 5 6 层序遍历 第0层[1] 第1层[2, 3] 第2层[4, 5, 6]4.2 锯齿形层序遍历pythondef zigzag_level_order(root): 锯齿形层序遍历Z字型遍历 if not root: return [] result [] queue deque([root]) left_to_right True # 控制遍历方向 while queue: level_size len(queue) level_nodes deque() # 使用双端队列方便左右添加 for _ in range(level_size): node queue.popleft() if left_to_right: level_nodes.append(node.val) else: level_nodes.appendleft(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(list(level_nodes)) left_to_right not left_to_right # 切换方向 return result锯齿形遍历示意图text1 / \ 2 3 / \ \ 4 5 6 锯齿形遍历 第0层[1] ← 从左到右 第1层[3, 2] ← 从右到左 第2层[4, 5, 6] ← 从左到右五、Morris遍历空间复杂度O(1)5.1 Morris中序遍历pythondef morris_inorder_traversal(root): Morris中序遍历 - 空间复杂度O(1) result [] current root while current: if not current.left: # 如果没有左子树访问当前节点并转向右子树 result.append(current.val) current current.right else: # 找到前驱节点 predecessor current.left while predecessor.right and predecessor.right ! current: predecessor predecessor.right if not predecessor.right: # 建立临时链接 predecessor.right current current current.left else: # 断开临时链接 predecessor.right None result.append(current.val) current current.right return resultMorris遍历核心思想利用叶子节点的空指针建立临时链接避免使用栈实现O(1)空间复杂度遍历过程中会临时修改树结构最后恢复5.2 Morris前序遍历pythondef morris_preorder_traversal(root): Morris前序遍历 - 空间复杂度O(1) result [] current root while current: if not current.left: result.append(current.val) current current.right else: predecessor current.left while predecessor.right and predecessor.right ! current: predecessor predecessor.right if not predecessor.right: result.append(current.val) # 前序遍历在此访问 predecessor.right current current current.left else: predecessor.right None current current.right return result六、遍历算法模板总结6.1 时间复杂度与空间复杂度对比遍历方式时间复杂度空间复杂度递归空间复杂度迭代空间复杂度Morris前序遍历O(n)O(h)O(h)O(1)中序遍历O(n)O(h)O(h)O(1)后序遍历O(n)O(h)O(h)O(1)层序遍历O(n)O(w)O(w)-注h为树高度w为树最大宽度n为节点总数6.2 遍历算法选择指南pythonclass TreeTraversalSelector: 遍历算法选择指南 staticmethod def select_algorithm(root, requirements): 根据需求选择遍历算法 Args: root: 二叉树根节点 requirements: 需求字典包含以下键 - space_complexity: O(1) 或 O(h) - traversal_type: preorder, inorder, postorder, level - need_iterative: True/False - tree_size: 树的大小大/小 traversal_type requirements.get(traversal_type, preorder) # 空间复杂度要求为O(1) if requirements.get(space_complexity) O(1): if traversal_type inorder: return morris_inorder_traversal(root) elif traversal_type preorder: return morris_preorder_traversal(root) # Morris后序遍历较复杂此处省略 # 需要迭代实现 if requirements.get(need_iterative, False): if traversal_type preorder: return preorder_traversal_iterative(root) elif traversal_type inorder: return inorder_traversal_iterative(root) elif traversal_type postorder: return postorder_traversal_iterative(root) elif traversal_type level: return level_order_traversal(root) # 默认使用递归 if traversal_type preorder: return preorder_traversal_recursive(root) elif traversal_type inorder: return inorder_traversal_recursive(root) elif traversal_type postorder: return postorder_traversal_recursive(root) elif traversal_type level: return level_order_traversal(root)七、实战应用与变种7.1 构建二叉树pythondef build_tree_from_preorder_inorder(preorder, inorder): 根据前序和中序遍历结果构建二叉树 if not preorder or not inorder: return None # 前序遍历第一个元素是根节点 root_val preorder[0] root TreeNode(root_val) # 在中序遍历中找到根节点的位置 root_index inorder.index(root_val) # 递归构建左右子树 root.left build_tree_from_preorder_inorder( preorder[1:1root_index], inorder[:root_index] ) root.right build_tree_from_preorder_inorder( preorder[1root_index:], inorder[root_index1:] ) return root7.2 验证二叉搜索树pythondef is_valid_bst(root): 验证二叉搜索树 - 利用中序遍历 stack [] current root prev_val float(-inf) while current or stack: while current: stack.append(current) current current.left current stack.pop() # 中序遍历中当前值应大于前一个值 if current.val prev_val: return False prev_val current.val current current.right return True7.3 二叉树序列化与反序列化pythondef serialize(root): 二叉树序列化为字符串层序遍历方式 if not root: return null result [] queue deque([root]) while queue: node queue.popleft() if node: result.append(str(node.val)) queue.append(node.left) queue.append(node.right) else: result.append(null) # 去除末尾的null while result and result[-1] null: result.pop() return ,.join(result) def deserialize(data): 从字符串反序列化为二叉树 if not data or data null: return None values data.split(,) root TreeNode(int(values[0])) queue deque([root]) i 1 while queue and i len(values): node queue.popleft() # 处理左子节点 if i len(values) and values[i] ! null: node.left TreeNode(int(values[i])) queue.append(node.left) i 1 # 处理右子节点 if i len(values) and values[i] ! null: node.right TreeNode(int(values[i])) queue.append(node.right) i 1 return root八、练习题与答案8.1 基础练习题题目1二叉树的最大深度pythondef max_depth(root): 二叉树的最大深度 if not root: return 0 return max(max_depth(root.left), max_depth(root.right)) 1题目2对称二叉树pythondef is_symmetric(root): 判断二叉树是否对称 def is_mirror(left, right): if not left and not right: return True if not left or not right: return False return (left.val right.val and is_mirror(left.left, right.right) and is_mirror(left.right, right.left)) return is_mirror(root, root) if root else True题目3二叉树的直径pythondef diameter_of_binary_tree(root): 二叉树的直径任意两节点间最长路径 diameter 0 def depth(node): nonlocal diameter if not node: return 0 left_depth depth(node.left) right_depth depth(node.right) # 更新直径 diameter max(diameter, left_depth right_depth) return max(left_depth, right_depth) 1 depth(root) return diameter8.2 进阶练习题题目4二叉树中的最大路径和pythondef max_path_sum(root): 二叉树中的最大路径和 max_sum float(-inf) def dfs(node): nonlocal max_sum if not node: return 0 # 计算左右子树的最大贡献值 left_gain max(dfs(node.left), 0) right_gain max(dfs(node.right), 0) # 当前节点的路径和 price_newpath node.val left_gain right_gain # 更新最大路径和 max_sum max(max_sum, price_newpath) # 返回当前节点的最大贡献值 return node.val max(left_gain, right_gain) dfs(root) return max_sum题目5二叉树的最近公共祖先pythondef lowest_common_ancestor(root, p, q): 二叉树的最近公共祖先 if not root or root p or root q: return root left lowest_common_ancestor(root.left, p, q) right lowest_common_ancestor(root.right, p, q) if left and right: return root return left if left else right九、总结与记忆技巧9.1 遍历口诀前序遍历根左右先访问根中序遍历左根右根在中间后序遍历左右根最后访问根层序遍历一层一层从左到右9.2 算法选择策略场景推荐算法理由简单实现递归遍历代码简洁易于理解避免递归栈溢出迭代遍历使用栈模拟控制性好空间要求严格Morris遍历O(1)空间复杂度需要层次信息层序遍历天然分层处理二叉搜索树操作中序遍历产生有序序列9.3 常见错误与避免方法空指针错误访问节点前检查是否为None递归栈溢出树深度大时使用迭代忘记恢复状态Morris遍历需要恢复临时链接顺序错误注意遍历顺序特别是迭代实现9.4 模板代码速查表python# 快速参考模板 class BinaryTreeTraversal: # 递归模板 def recursive_traversal(self, root, order): res [] def dfs(node): if not node: return if order pre: res.append(node.val) dfs(node.left) if order in: res.append(node.val) dfs(node.right) if order post: res.append(node.val) dfs(root) return res # 迭代模板标记法 def iterative_traversal(self, root, order): if not root: return [] res, stack [], [(root, False)] while stack: node, visited stack.pop() if not node: continue if visited: res.append(node.val) else: if order pre: stack.extend([(node.right, False), (node.left, False), (node, True)]) elif order in: stack.extend([(node.right, False), (node, True), (node.left, False)]) else: # post stack.extend([(node, True), (node.right, False), (node.left, False)]) return res # 层序遍历模板 def level_traversal(self, root): if not root: return [] res, queue [], deque([root]) while queue: level [] for _ in range(len(queue)): node queue.popleft() level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res掌握二叉树遍历是理解更复杂树结构算法的基础。通过理解每种遍历的原理、实现方式及应用场景可以灵活解决各种树相关的问题。建议结合实际题目练习加深对遍历算法的理解。