[Data Structure] 二叉搜索树(Binary Search Tree)

1. 二叉搜索树,可以用作字典,或者优先队列。

2. 根节点 root 是树结构里面唯一一个其父节点为空的节点。

3. 二叉树搜索树的属性:

  假设 x 是二叉搜索树的一个节点。如果 y 是 x 左子树里面的一个节点,则 y.key <= x.key。如果 y 是 x 右子树里面的一个节点,则 x.key <= y.key。

4. 通过一次中序遍历 ( inorder tree walk ),可以将二叉搜索树的元素按照排好的顺序输出。例子如下

1 INORDER-TREE-WALK(x)
2     if x != NIL
3         INORDER-TREE-WALK(x.left)
4         print x.key
5         INORDER-TREE-WALK(x.right)

5. 二叉搜索树不仅支持搜索操作,还支持查找最小值、最大值、后继节点( successor )、前驱节点( predecessor )

搜索,通过递归能轻易实现搜索操作.

TREE-SEARCH(X)
    if x == NIL or k == x.key
        return x
    if k < x.key
        return TREE-SEARCH(x.left)
    else 
        return TREE-SEARCH(x.right)

迭代版代码如下

ITERATIVE-TREE-SEARCH(x, k)
    while x != NIL and k != x.key
        if x < x.key
            x = x.left
        else
            x = x.right 
    return x

最小值,是最左边的节点

TREE-MINIMUM(x)
    while x.left != NIL
        x = x.left
    return x

最大值,是最右边的节点

TREE-MAXIMUM(x)
    while x.right != NIL
        x = x.right
    return x

节点 x 的后继节点,是值在树结构中比 x 大的最小节点。

后继节点有两种情况

a. 当节点 x 有右子树,则后继节点为右子树中最小值。

b. 当节点 x 没有右子树并有后继节点,则 x 的后继节点为 x 的某个祖先节点,该祖先节点满足其左子节点也是 x 的祖先节点。也就是说,从 x 往 root 的父节点路径查找,第一个向右拐的目标节点(即,父节点),就是后继节点。

TREE-SUCCESSOR(x)
    if x.right != NIL
        return TREE-MINIMUM(x)
    y = x.p
    while y != NIL and x == y.right
        x = y
        y = y.p
    return y

前驱节点和后继节点的查找思路相似。

6. 插入节点 x,有两个步骤:1) 搜索合适插入的位置 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
    elseif z.key < y.key
        y.left = z
    else
        y.right = z

7. 删除节点 x ,有下面三种情况

  a. 没有子节点,则直接删除

  b. 仅有一个子节点,则用子节点代替待删除节点。

  c. 有两个子节点,则找到 x 的后继节点 y。y 必然在 x 的右子树里面最左边的节点。然后,用 y 覆盖 x, 删除 y 原来的节点。由于 y 是右子树里最左边的节点,所以没有左字节,有或者没有右子节点,此时便是 a 或 b 的情况。

 下面是根据上面逻辑写代码实现。和书本的版本比起来,代码行数多些,不过可读性较好。

TREE-DELETE(node)
    if node.left == NIL && node.right == NIL
        node.parent = NIL
        return
    if node.left != NIL && node.right != NIL
        newN = TREE-MINIMUM(node.right)
        node.key = newN.key
        TREE-DELETE(newN)
        return
    if node.left != NIL
        p = node.p
        s = node.left
        p.left = s
        s.p = p
        node.p = NIL
        node.left = NIL
    if node.right != NIL
        p = node.p
        s = node.right
        p.right = s
        s.p = p
        node.p = NIL
        node.right = NIL

参考资料

Binary search tree. Removing a node, algolist

12 Binary Search Trees, Introduction to algorithms

第 12 章 二叉搜索树,《算法导论》

原文地址:https://www.cnblogs.com/TonyYPZhang/p/5713268.html