二叉查找树的查找、插入、删除

二叉查找树(英语:Binary Search Tree),也称为二叉搜索树、有序二叉树(Ordered Binary Tree)或排序二叉树(Sorted Binary Tree),是指一棵空树或者具有下列性质的二叉树:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  3. 任意节点的左、右子树也分别为二叉查找树;
  4. 没有键值相等的节点。

二叉查找树的查找、插入的时间复杂度较低,为O(log n)

二叉查找树的中序遍历结果是一个递增的数列

完整代码:BST.py

BST查找

# 二叉查找树的查找
def searchBST(self, root: TreeNode, x: int) -> TreeNode:
    # 如果树为空,则肯定不存在值为x的节点,返回空
    if root is None:
        return None
    p = root
    # 当p不空,说明没有查找结束
    while p is not None:
        # 如果p的值等于x,则p就是我们要找的节点,返回p
        if p.val == x:
            return p
        # 节点p的值大于x,说明x在p的左子树
        if p.val > x:
            p = p.left
        # 节点p的值小于x,说明x在p右左子树
        elif p.val < x:
            p = p.right
    # 若一直查找到空节点,说明整个树中没有值为x的节点,返回空
    return None

BST插入

# 二叉查找树插入,将x插入根节点为root的二叉查找树
def insertIntoBST(self, root: TreeNode, x: int) -> TreeNode:
    # 树为空,则直接插入到根节点
    if root is None:
        root = TreeNode(x)
        return root
    # parent指向当前节点的父节点
    p = root
    parent = p
    while p is not None:
        if p.val == x:
            print("插入失败,二叉搜索树中已经存在值为x的节点")
            return None
        if p.val > x:
            parent = p
            p = p.left
        elif p.val < x:
            parent = p
            p = p.right
    # 循环完成,parent指向p的父节点,值将被插入到parent的左孩子或者右孩子
    if parent.val > x:
        parent.left = TreeNode(x)
    else:
        parent.right = TreeNode(x)
    return root

BST删除

  1. 待删除的节点(p)是叶子节点(左右孩子均为空),则直接删除p。

  2. p有且仅有一个孩子,则将p的父节点和孩子相连,然后删除p。

  3. p有两个孩子,则:

    1. 将p的直接后继的值拷贝到p
    2. 删除p的直接后继

    1. 将p的直接前驱的值拷贝到p
    2. 删除p的直接前驱

    直接后继:节点值大于该节点值并且值最小的节点,也就是右子树中值最小的节点,也就是右子树中最左侧的节点。

    直接前驱:节点值小于该节点值并且值最大的节点,也就是左子树中值最大的节点,也就是左子树中最右侧的节点。

def deleteNode(self, root: TreeNode, key: int) ->TreeNode:
    # 首先要找到值为key的节点p,用parent记录p的父节点
    p = root
    parent = p
    while p is not None:
        if p.val == key:
            break
        elif p.val > key:
            parent = p
            p = p.left
        elif p.val < key:
            parent = p
            p = p.right
    if p is None:
        print("树中没有值为key的节点,无法删除!")
        return root
    # 到这里,p是值为key的节点,parent是p的父节点
    # 1. 如果p是叶子节点
    if p.left is None and p.right is None:
        # 判断p是parent的左孩子还是右孩子
        if parent.left is p:
            parent.left = None
        elif parent.right is p:
            parent.right = None
        # p是根节点
        elif parent is p:
            return None
        return root
    # 2.1 如果p只有左孩子
    elif p.left is not None and p.right is None:
        if parent.left is p:
            parent.left = p.left
        elif parent.right is p:
            parent.right = p.left
        elif parent is p:
            return p.left
        return root
    # 2.2 如果p只有右孩子
    elif p.left is None and p.right is not None:
        if parent.left is p:
            parent.left = p.right
        elif parent.right is p:
            parent.right = p.right
        elif parent is p:
            return p.right
        return root
    # 3. 如果p有两个孩子
    elif p.left is not None and p.right is not None:
        # 3.1. 将p的直接后继node的值拷贝到p
        # 3.1.1 先找到p的直接后继node,node_parent是nod的父节点
        node_parent = p
        node = p.right
        while node.left is not None:
            node_parent = node
            node = node.left
        # 此时node是待删除节点p的直接后继,node_parentnode的父节点。
        # 3.1.2 将node的值拷贝到p
        p.val = node.val
        # 3.2. 删除p的直接后继node。由于node是p的右子树的左节点,那么node肯定没有左孩子,可能有右孩子。
        # 3.2.1 如果node没有右孩子
        if node.right is None:
            if node_parent.left is node:
                node_parent.left = None
            elif node_parent.right is node:
                node_parent.right = None
        # 3.2.2 如果node有右孩子
        elif node.right is not None:
            if node_parent.left is node:
                node_parent.left = node.right
            elif node_parent.right is node:
                node_parent.right = node.right
        return root
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉查找树(Binary Search Tree,BST)和红黑树(Red-Black Tree)是两种常见的二叉树数据结构,它们在插入删除查找操作上有一些区别。 1. 结构特点: - 二叉查找树:每个节点的左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。 - 红黑树:除了具备二叉查找树的特点外,还满足以下红黑树性质: - 每个节点要么是红色,要么是黑色。 - 根节点是黑色。 - 每个叶子节点(NIL节点,空节点)是黑色。 - 如果一个节点是红色的,则它的两个子节点都是黑色的。 - 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。 2. 平衡性: - 二叉查找树:在最坏情况下,二叉查找树可能会退化成链表,导致插入删除查找操作的时间复杂度为O(n)。 - 红黑树:通过保持红黑树性质,红黑树能够保持相对平衡,插入删除查找操作的时间复杂度为O(log n)。 3. 插入删除操作: - 二叉查找树插入删除操作只需按照二叉查找树的规则进行即可,不需要进行额外的平衡操作。 - 红黑树:插入删除操作需要通过旋转和重新着色等操作来保持红黑树的平衡性。 4. 存储空间: - 二叉查找树:每个节点只需存储键值和指向左右子节点的指针,相对较小。 - 红黑树:每个节点需要额外存储颜色信息,相对于二叉查找树会占用更多的存储空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值