算法(③二叉树)
遍历算法
TreeNode 类:
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right
创建节点
# 创建节点
root = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)# 连接节点
root.left = node2
root.right = node3
node2.left = node4
node2.right = node5
前序遍历 (Pre-order Traversal)
def preorder_traversal(root):if root is None:return []result = []result.append(root.val) # 访问根节点result.extend(preorder_traversal(root.left)) # 递归访问左子树result.extend(preorder_traversal(root.right)) # 递归访问右子树return result# 假设我们已经创建了上面那棵树
# preorder_traversal(root) 的结果将是 [1, 2, 4, 5, 3]
中序遍历 (In-order Traversal)
def inorder_traversal(root):if root is None:return []result = []result.extend(inorder_traversal(root.left)) # 递归访问左子树result.append(root.val) # 访问根节点result.extend(inorder_traversal(root.right)) # 递归访问右子树return result# inorder_traversal(root) 的结果将是 [4, 2, 5, 1, 3]
后序遍历 (Post-order Traversal)
def postorder_traversal(root):if root is None:return []result = []result.extend(postorder_traversal(root.left)) # 递归访问左子树result.extend(postorder_traversal(root.right)) # 递归访问右子树result.append(root.val) # 访问根节点return result# postorder_traversal(root) 的结果将是 [4, 5, 2, 3, 1]
二叉搜索树
前置条件:节点类
我们继续使用之前定义的 TreeNode 类:
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right
插入节点 (Insertion)
def insert_into_bst(root, val):"""在二叉搜索树中插入一个新节点:param root: 当前子树的根节点:param val: 要插入的值:return: 插入新节点后的根节点"""# 递归终止条件:如果当前节点为空,说明找到了插入位置,创建新节点并返回if not root:return TreeNode(val)# 如果要插入的值小于当前节点的值,向左子树递归if val < root.val:root.left = insert_into_bst(root.left, val)# 如果要插入的值大于当前节点的值,向右子树递归elif val > root.val:root.right = insert_into_bst(root.right, val)# 返回当前根节点,因为它的子树可能已经改变return root# 示例:在 BST 中插入 7
# 初始 BST:
# 4
# / \
# 2 7
# / \
# 1 3
root = TreeNode(4)
root.left = TreeNode(2, TreeNode(1), TreeNode(3))
root.right = TreeNode(7)print("插入前的二叉搜索树(前序遍历):", end=" ")
def preorder(node):if node:print(node.val, end=" ")preorder(node.left)preorder(node.right)
preorder(root)
print()root = insert_into_bst(root, 5) # 插入 5print("插入 5 后的二叉搜索树(前序遍历):", end=" ")
preorder(root)
print()
删除节点 (Deletion)
def delete_node(root, key):"""在二叉搜索树中删除一个节点:param root: 当前子树的根节点:param key: 要删除的值:return: 删除节点后的根节点"""if not root:return root# 1. 查找要删除的节点if key < root.val:root.left = delete_node(root.left, key)elif key > root.val:root.right = delete_node(root.right, key)# 2. 找到要删除的节点(root.val == key)else:# 情况 1 和 2:节点只有一个子节点或没有子节点if not root.left:return root.rightelif not root.right:return root.left# 情况 3:节点有两个子节点# 找到中序遍历的后继节点(右子树中最小的节点)temp_node = find_min_node(root.right)# 用后继节点的值替换当前节点的值root.val = temp_node.val# 递归地删除后继节点root.right = delete_node(root.right, temp_node.val)return rootdef find_min_node(node):"""辅助函数:找到子树中的最小节点"""current = nodewhile current.left:current = current.leftreturn current# 示例:删除节点 4
# 初始 BST:
# 5
# / \
# 3 6
# / \ \
# 2 4 7
root = TreeNode(5)
root.left = TreeNode(3, TreeNode(2), TreeNode(4))
root.right = TreeNode(6, None, TreeNode(7))print("删除 4 前的二叉搜索树(前序遍历):", end=" ")
preorder(root)
print()root = delete_node(root, 4) # 删除 4print("删除 4 后的二叉搜索树(前序遍历):", end=" ")
preorder(root)
print()# 示例:删除节点 5(有两个子节点)
# 初始 BST:
# 5
# / \
# 3 6
# / \ \
# 2 4 7
root = TreeNode(5)
root.left = TreeNode(3, TreeNode(2), TreeNode(4))
root.right = TreeNode(6, None, TreeNode(7))print("删除 5 前的二叉搜索树(前序遍历):", end=" ")
preorder(root)
print()root = delete_node(root, 5) # 删除 5print("删除 5 后的二叉搜索树(前序遍历):", end=" ")
preorder(root)
print()