美文网首页
第12章 二叉搜索树

第12章 二叉搜索树

作者: 明若晴空 | 来源:发表于2019-11-08 21:38 被阅读0次

12.1、二叉搜索树

二叉搜索树,使用一个链表数据结构来表示结点。每个结点是一个对象,包含属性key、left、right、p,分别代表其值、左孩子、右孩子和父节点。
子结点或父节点不存在时,属性值为NIL。
根节点是树中唯一父指针为NIL的结点。

二叉搜索树的性质:
二叉搜索树的每个结点,都满足其左子树上的结点都小于等于该节点的值,其右子树上的结点都大于等于该节点的值。

定理 12.1:
一棵有n个结点的树,使用中序遍历法需要 O(n)时间。

12.2、查询二叉搜索树

查找

在二叉搜索树上的查询的运行时间为O(h),其中h为树的高度。
其搜索伪代码如下:

 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);

最大关键字搜索和最小关键字搜索

搜索最小关键字的伪代码:

TREE-MINIMUM(x)
while x.left 不等于 nil
    x = x.left;
return x;

对称的,搜索最大关键字的伪代码:

TREE-MAXIMUM(x)
while x.right 不等于 nil
    x = x.right;
return x;

这两种查询的运行时间都是O(h),其中h为树的高度。

后继和前驱

按照中序遍历法,获取一个节点的后继的伪代码:

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;

说明:

  1. 节点x的右子树非空,那么其后继就是右子树中最小的结点;
  2. 结点x的右子树为空,并有一个后继,那么这个后继就是结点x的有左孩子的最底层(最靠近根节点)的祖先,该后继也是结点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;

12.3、插入和删除

插入

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;
else
    if y.key <= z.key
        y.right = z;
    else
        y.left = z;

说明:

  • 遍历过程中,y是记录z的父节点位置;
  • while循环中向右或向左移动,向下遍历寻找z的应该插入的位置,即x为nil的位置,此时记录x的父节点y;
  • 最后,设置新节点z的父节点,并设置z为父节点的左子节点或右子节点。

删除

二叉树删除子节点z的几种情况:

  1. z没有左孩子,就直接用右孩子来替换z。右孩子可以是nil,也可以不是nil。
  2. z有左孩子,并且只有这一个孩子,就直接用左孩子来替换z。
  3. z既有左孩子,又有右孩子。这时,要在z的右子树中寻找z的后继y。这个后继y肯定没有左孩子。那么这种情况又分为两种:y是z的右孩子和y不是z的右孩子
    3.1. 后继y,是z的右孩子,就直接用y替换z,继续保留y的右孩子(y是没有左孩子的)。
    3.2. 后继y,在z的右子树中,但是不是z的右孩子。这种情况下,先用y的右孩子替换y的位置(y没有左孩子),再用y替换z的位置。

这个过程中,涉及到移动子树,因此要先定义一个移动子树的过程TRANSPLANT。主要是要替换树的父节点
在树T中,用子树v替换子树u,移动子树的伪代码:

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

利用TRANSPLANT移动子树的过程,从二叉搜索树中删除节点z的伪代码:

TREE-DELETE(T,z)
    //对应z没有左孩子节点
    if z.left == nil
        TRANSPLANT(T, z, z.right);
    //对应z有左孩子节点,但是没有右孩子节点
    else if z.right == nil
        TRANSPLANT(T, z, z.left);
    else
        //对应z既有左孩子节点,又有右孩子节点,先去右子树中找z的后继
        y = TREE-MINIMUM(z.right);
        //对应后继y不是z的右孩子,用y构建z的父节点的子树
        if y.p != z
            TRANSPLANT(T, y, y.right)
            y.right = z.right;
            y.right.p = y;
        //对应后继是z的右孩子的情况,直接用z的右孩子替换z的位置
        TRANSPLANT(T, z, y)
        y.left = z.left;
        y.left.p = y;

插入和删除的运行时间均为O(h),h为树的高度 **

12.4、随机构建二叉搜索树

随机构建二叉搜索树定义如下:
按随机次序插入n个关键字到一棵初始空树中,从而生成的树。

一棵n个不同关键字的随机构建二叉树的期望高度为O(lg n);**

相关文章

  • 每日一题之《剑指offer》62,63题

    第62题:二叉搜索树的第k个节点 难易度:⭐⭐ 解析:二叉搜索树的特点就是如果中序遍历二叉搜索树,打印出来的节点v...

  • 数据结构与算法之二叉搜索树(八)

    目录 二叉搜索树概念二叉搜索树的接口设计,包括增,删,改,查平衡二叉搜索树 一 二叉搜索树 二叉搜索树是二叉树的一...

  • 面试题54. 二叉搜索树的第k大节点

    二叉搜索树的第k大节点 题目描述 给定一棵二叉搜索树,请找出其中第k大的节点。 示例: 提示:1 ≤ k ≤ 二叉...

  • Algorithm小白入门 -- 二叉搜索树

    二叉搜索树二叉搜索树 BSTBST 的基本操作计算合法的 BST 1. 二叉搜索树 BST 二叉搜索树(Binar...

  • 剑指offer | 二叉搜索树的第k个结点

    二叉搜索树的第k个结点 给定一棵二叉树,请找出其中的第k大的结点 分析:二叉搜索树的中序遍历是递增顺序的

  • 二叉搜索树

    二叉搜索树 图解二叉树搜索算法图解:二叉搜索树算法二叉查找树(Binary Search Tree),(又:二叉搜...

  • 23-红黑树

    1.二叉搜索树(BST)继承二叉树(BinaryTree) 2.平衡二叉搜索树(BBST)继承二叉搜索树(BST)...

  • 【leetcode-树】二叉搜索树中第K小的元素

    【leetcode-树】二叉搜索树中第K小的元素 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找...

  • Java日记2018-05-19

    第一题 二叉搜索树的第 K 个结点二叉搜素树的中序遍历访问队列,自然的满足升序排序的条件,中序遍历二叉搜索树找到第...

  • 2019-03-25待提高

    1.#### 二叉搜索树中第K小的元素给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k ...

网友评论

      本文标题:第12章 二叉搜索树

      本文链接:https://www.haomeiwen.com/subject/abawbctx.html