算法学习笔记——数据结构:二叉搜索树BST

这篇博客介绍了二叉搜索树(BST)的基本概念和特性,包括中序遍历得到递增序列、查找节点、插入操作、删除操作以及验证BST的合法性。插入操作通过递归找到合适位置插入新节点,保持BST性质。删除节点时需考虑无子节点、一个子节点和两个子节点的情况。验证BST合法性使用了辅助函数,通过维护最小值和最大值范围来确保所有子树满足BST条件。
摘要由CSDN通过智能技术生成

二叉搜索树BST

二叉搜索树BST,即BinarySearchTree,其特性是:

  • 对于任意节点,如果其值为val,则左子树所有节点值小于等于val,且右子树所有节点值大于等于val
    注意利用此特性,避免多余的访问
    def traverseBST(node: TreeNode, target: int):
    	"""BST遍历框架"""
        if node is None:
            return
        if node.val == target:
            # 找到目标,做点什么
        if target < node.val:  # 进入左子树
            traverseBST(node.left, target)
        if target > root.val:  # 进入右子树
            traverseBST(node.right, target)
  • 中序遍历BST,一定得到一个递增序列
  • BST子树,向左走到底,就是值最小的节点,向右走到底就是值最大的节点

插入新节点

LeetCode 701. 二叉搜索树中的插入操作

# 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 insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        if root is None:  # 找到插入的空位
            return TreeNode(val)
        if val < root.val:  # 进入左子树
            root.left = self.insertIntoBST(root.left, val)
        if val > root.val:  # 进入右子树
            root.right = self.insertIntoBST(root.right, val)
        return root
       

判断BST合法性

LeetCode 98. 验证二叉搜索树

  • 注意陷阱:不能只看每个节点和它的左右儿子是否满足要求,应该要求整个左子树、右子树都满足要求才行
  • 如何保证左子树、右子树的所有节点都满足要求?
    可以增加函数参数,维护min和max,限制每个节点的合法范围,从而检查节点是否合法

技巧:如果当前结点对下面的子节点有整体影响,可以借助函数参数传递更多信息

# 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 isValidBST(self, root: TreeNode) -> bool:
        def valid(node, min, max):
            if node is None:
                return True
            if min is not None and node.val <= min:
                return False
            if max is not None and node.val >= max:
                return False
            return valid(node.left, min, node.val) and valid(node.right, node.val, max)

        return valid(root, None, None)

在BST中删除一个数

LeetCode 450. 删除二叉搜索树中的节点
总体框架是查找目标节点然后删除,但注意,删除后应该保持BST性质不变(分情况处理:无子节点、一个子节点、 两个子节点)

# 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 deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        def delete(node, key):
            """找到并删除节点,删除后应该保持BST性质不变"""
            if node is None:
                return None
            if node.val == key:  # 找到了,删除当前结点
                if node.left is None and node.right is None:  # 没有子节点
                    return None
                if node.left is None:  # 有一个子节点,让子节点接替自己的位置
                    return node.right
                if node.right is None:  # 有一个子节点,让子节点接替自己的位置
                    return node.left

                # 剩下同时有左右子树的情况,可以用左子树中最大的节点接替自己,也可用右子树最小的节点接替自己

                # 找到右子树最小的节点
                minNode = node.right
                while minNode.left is not None:
                    minNode = minNode.left

                # 接替自己,然后删除右子树中原来的节点(此节点位于最左侧,一定没有子节点)
                # ps. 当内部数据复杂时,直接修改指针更好
                node.val = minNode.val
                node.right = delete(node.right, minNode.val)

            elif node.val > key:  # 进入左子树
                node.left = delete(node.left, key)

            elif node.val < key:  # 进入右子树
                node.right = delete(node.right, key)
            return node

        return delete(root, key)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值