二叉搜索树(binary search tree)

BST1

性质

设 x 是二叉搜索树中的一个结点。如果 y 是 x 左子树中的一个结点,那么 y.key ≤ x.key。如果 y 是 x 右子树中的一个结点,那么 y.key ≥ x.key。

特性

期望高度:height = O(lgn)

基本操作平均时间复杂度:Operations = Θ(lgn)

操作

遍历:时间复杂度 θ(n),n 为总结点数。

INORDER_TREE_WALK
    if x != NIL
        INORDER_TREE_WALK(x.left)
        print x.key
        INORDER_TREE_WALK(x.right)

搜索指定键值:中序遍历查找指定键值。时间复杂度 O(height)。

TREE_SEARCH(x, k)
    if x == NIL or k == x.key
        return x
    if k < x.key
        return TREE_SEARCH(x.left, k)
    else
        return TREE_SEARCH(x.right, k)
ITERATIVE_TREE_SEARCH(x, k)
    while x != NIL and k != x.key
        if k < x.key
            x = x.left
        else
            x = x.right
    return x

查找最小值:递归查找最左结点。时间复杂度 O(height)。

TREE_MINIMUM(x)
    while x.left != NIL
        x = x.left
    return x

查找最大值:递归查找最右结点。时间复杂度 O(height)。

TREE_MAXIMUM(x)
    while x.right != NIL
        x = x.right
    return x

后继:时间复杂度 O(height)。

实现分为两种情况:
* 结点 x 的右子树非空,则右子树的最左结点就是 x 的后继。
* 结点 x 的右子树为空,则后继 y 满足: y 的左子树存在且同时是 x 的祖先, y 是符合前面性质的最底层的 x 的祖先。

TREE_SUCCESSOR(x)
    if x.right != NIL
        return TREE_MINIMUM(x.right)
    y = x.p
    while y != NIL and x == y.right
        x = y
        y = y.p
    return y

前驱:时间复杂度 O(height)。

实现分为两种情况:
* 结点 x 的左子树非空,则左子树的最右结点就是 x 的前驱。
* 结点 x 的左子树为空,则前驱 y 满足:y 的右子树存在且同时是 x 的祖先,y 是符合前面性质的最底层的 x 的祖先。

TREE_PREDECESSOR(x)
    if x.left != NIL
        return TREE_MAXIMUM(x.left)
    y = x.p
    while y != NIL and x == y.left
        x = y
        y = y.p
    return y

插入:时间复杂度 O(height)。

实现:
1. 查找新结点放置的位置。
* 从树的根节点开始,新结点和当前结点的值比较,根据情况向左或右遍历。
* 循环a,直到得出的当前节点为NILL为止,这个当前结点的位置就是新结点要插入的位置。
2. 放置新结点。根据新结点与前面得到的结点的父结点比较,确定位置并插入。

TREE_INSERT(T, z)
    y = NIL
    x = T.root
    while x != NIL
        y = x
        if z.key < x.key
            x = x.left
        else
            x = x.right
    z.p = y
    if y == NIL
        T.root = z // tree T was empty
    elseif z.key < y.key
        y.left = z
    else
        y.right = z

删除:时间复杂度 O(height)

实现策略分为三种情况,设要删除的结点为 z :
* 如果 z 没有孩子结点,那么简单地将它删除,并修改它的父结点,用NIL作为孩子来替换 z 。
* 如果 z 有一个孩子,那么将这个孩子提升到树中 z 的位置上,并修改 z 的父结点,用 z 的孩子来替换 z 。
* 如果 z 有两个孩子, 那么找 z 的后继 y (一定在 z 的右子树上),并让 y 占据树中 z 的位置。z 的原右子树部分称为y的新的右子树,并且 z 的左子树成为 y 的新的左子树。

TRANSPLANT(T, u, v)
    if u.p == NIL
        T.root = u
    elseif u == u.p.left
        u.p.left = v
    else
        u.p.right = v
    if v != NIL
        v.p = u.p

TREE_DELETE(T, z)
    if z.left == NIL
        TRANSPLANT(T, z, z.right)
    elseif z.right == NIL
        TRANSPLANT(T, z, z.left)
    else 
        y = TREE_MINIMUM(z.right)
        if y.p != z
            TRANSPLANT(T, y, y.right)
            y.right = z.right
            y.right.p = y
        TRANSPLANT(T, z, y)
        y.left = z.left
        y.left.p = y

猜你喜欢

转载自blog.csdn.net/bnbjin/article/details/78697986