• 算法导论笔记:12二叉搜索树


    1:概念

           二叉搜索树也叫二叉排序树,它支持的操作有:SEARCH, MINIMUM, MAXIMUM, PREDECESSOR, SUCCESSOR, INSERT, DELETE。所以,一颗二叉搜索树既可以作为一个字典,又可以作为一个优先队列。

           二叉搜索树的基本操作时间与这棵树的高度成正比。二叉搜索树的高度可以从Ө(lgn) Ө(n)

          

           二叉搜索树可以用链表来存储,每个节点包括:key,卫星数据,left, right, p指针。

           二叉搜索树的性质是:设x为二叉查找树中的一个节点,如果y是x的左子树中的一个节点,则y.key <= x.key;如果y是x的右子树中的一个节点,则y.key >= x.key。这个性质对树中的每个节点都成立。对于一组值,可以用不同的二叉搜索树表示。如下图:

     

    二:按序输出

           中序遍历二叉搜索树,就可以将树中的元素按序输出。中序遍历的时间是:Ө(n)

     

    三:查询操作

           二叉搜索树除了支持SEARCH操作之外,还支持MINIMUM, MAXIMUM, SUCCESSOR,  PREDECESSOR的查询操作。这些操作都可以在O(h)时间内完成,h为二叉搜索树的高度

     

    1:SEARCH

           递归算法:

    TREE-SEARCH(x, k)

           If x == null 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 !=  NULL and k !=  x.key

                  If k < x.key

                         x = x.left

                  Else x = x.right

           Return x

     

    2:MAXIMUM, MINIMUM

           找最小元素,就是从树根开始,一直沿着左子树向下寻找,直到找到一个节点,它没有左孩子。

           找最大元素,就是从树根开始,一直沿着右子树向下寻找,直到找到一个节点,它没有右孩子。

    TREE-MINIMUM(x)

           while x.left != NULL

                  x= x.left

           return x

     

    TREE-MAXIMUM(x)

           while x.right != NULL

                  x=x. right

           return x

     

    3SUCCESSOR, PREDECESSOR

           给定一个二叉搜索树中的一个节点,有时候需要中序遍历的次序查找它的后继或者前驱。

           节点x的后继就是大于x.key的最小关键字的节点。如果x的右子树非空,则x的后继就是x的右子树中的最小节点。如果x的右子树为空,则需要从x开始向上寻找,直到找到x的一个祖先,他有左孩子。这个祖先就是x的后继。

    TREE-SUCCESSOR(x)

           If x.right != NULL

                  Return TREE-MINIMUM(x.right)

           Y= x.p

           While y != NULL and x== y.right

                  X = y

                  Y = y.p

           Return y

     

           如果节点中不含有p指针的话,则是:

    TREE-SUCCESSOR2(T, x)

           If x.right != NULL

                  Return TREE-MINIMUM(x.right)

           Y = T.root

           Cur = NULL

           While y != NULL and x.key  != y.key

                  If x.key < y.key

                         Cur = y

                         Y = y.left

                  Else

                         Y = y.right

           Return cur

     

           节点x的前驱就是小于x.key的最大关键字的节点。如果x的左子树非空,则x的后继就是x的左子树中的最大节点。如果x的左子树为空,则需要从x开始向上寻找,直到找到x的一个祖先,他有右孩子。这个祖先就是x的前驱。

    TREE-PREDECESSOR(x)

           If x.left != NULL

                  Return TREE-MAXIMUM(x.left)

           Y= x.p

           While y != NULL and x== y.left

                  X = y

                  Y = y.p

           Return y

     

           如果节点中不含有p指针的话,则是:

    TREE- PREDECESSOR (T,x)

           If x.left != NULL

                  Return TREE- MAXIMUM (x. left)

           Y = T.root

           Cur = NULL

           While y != NULL and  x.key != y.key

                  If x.key > y.key

                         Cur = y

                         Y = y. right

                  Else

                         Y = y.left

           Return cur

     

    四:插入和删除

           插入和删除操作都会改变二叉搜索树,但是同时要保证二叉搜索树的性质

    插入和删除操作的运行时间为O(h),h为二叉搜索树的高度

     

    1:插入

           要插入的新节点都将成为一个叶子节点,插入操作较简单,代码如下:

    TREE-INSERT(T, z)

           Y = NULL

           X = T.root

           While x != NULL

                  Y= x

                  If z.key < x.key

                         X= x.left

                  Else  x = x.right

     

           z.p = y

           if y == NULL

                  T.root = z

           Else if z.key < y.key

                  y.left = x

           else

                  y.right = x

     

    2:删除

           删除操作较复杂,需要区分不同的情况:

           a:如果z没有孩子节点,则简单的将z删除即可

           b:如果z有一个孩子节点,则将孩子节点提升到z的位置上即可

           c:如果z有两个孩子,那么需要找到z的后继yy一定在z的右子树中。如果yz的右孩子,那么y一定没有左孩子(参见后继算法),此时用y替换z即可;如果y不是z的右孩子,则需要用y的右孩子替换y,然后用y替换z

    如下图:

     

           为了在二叉搜索树中移动子树,定义子过程TRANSPLANT,它用一颗子树替换另一颗子树:

    TRANSPLANT(T,u,v)   //用v替换u

           If u.p == NULL

                  T.root = v

           Else if u == u.p.left

                  u.p.left = v

           else u.p.right = v

           if  v != NULL

                  v.p = u.p

           该过程只是使u的双亲成为v的双亲,并没有处理v的孩子节点的更新,这需要调用者来处理:

     

    TREE-DELETE(T, z)

           If z.left == NULL

                  TRANSPLANT(T, z, z.right)

           Else if z.right == NULL

                  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

     

    五:随机构建二叉搜索树

           二叉搜索树的操作都能在O(h)时间内完成,h是二叉搜索树的高度。在构建二叉搜索树的时候,如果n个关键字是按照递增的顺序插入的话,那么这个树的高度为n-1这是最坏的情况,所以可以对n个关键字进行随机化:随机构建二叉搜索树为按随机次序插入关键字到一颗初始空树,这里输入关键字排列共有n!种,每个个排列都是等可能的。

           一颗有n个不同关键字的随机构件二叉搜索树的期望高度为O(lg n)

  • 相关阅读:
    获取Activity中得到焦点的EditText
    SwipeRefreshLayout嵌套ScrollView包裹复杂头布局和RecyclerView
    摄像机识别图片中的手机号
    Glide 加载图片
    反射,元类
    类与实例
    多态
    sys模块理解补充
    python中os模块再回顾
    面向对象之封装
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247235.html
Copyright © 2020-2023  润新知