树形查找算法

本文章内所有排序皆以增序(非降序)排列。

一、二叉排序树(BST)

1. 二叉排序树的定义

        左子树的所有结点<根节点<右子树,并且此规则适用于所有子树。

        对二叉排序树进行中序遍历,可以得到一个增序序列。

2. 二叉排序树的查找

        二叉排序树的类似于对一个有序序列的二分查找,而树形结构相当于已经提供了二分的索引,不必自己去计算下一个需要比较的元素的位置。

        具体的查找步骤如下:

  1. 先和根节点比较,若小于根节点,那么就去左子树去查找;若大于根节点那么去右子树查找;若等于根节点,查找完毕。
  2. 对进入的下一个节点应用步骤1,直到查找到对于节点或者查找失败(抵达叶子节点,且叶子节点也不对)。

伪代码如下:

struct BST{
    int data;           //数据域
    BST* leftChild;     //左子树
    BST* rightChild;    //右子树
};

BST* searchBST(BST *node, const int &data){
    if(node == NULL || data == node->data){      //当前树空或者等于根节点值,直接返回该节点
        return node;
    } else if (data < node->data) {              //小于根节点值,去左子树查找
        if (node->leftChild == NULL) {           //左子树为空,代表查找失败,返回空节点
            return NULL;
        }
        return search(node->leftChild, data);    //进入左子树查找
    } else if (data > node->data) {              //大于根节点,去右子树查找
        if (node->rightChild == NULL) {          //右子树为空,代表查找失败 ,返回空节点
            return NULL;
        }
        return search(node->rightChild, data)    //进入右子树查找
    }
    return NULL;                                 //防止编译器报错
}

3.二叉排序树的插入

        插入就是当查找失败时的那个节点,即为需要插入的位置。

4.二叉排序树的生成

        就是将一个序列,根据插入算法,将所有节点依次插入到树上。

5.二叉排序树的删除

        删除有三种情况:

  1. 当被删除节点是叶子节点时,可以直接删除
  2. 当被删除节点只有一个孩子时,直接用孩子节点替代父节点,子节点及其以后的序列不发生变化
  3. 当被删除节点有两个孩子时,用子树中的直接后继(中序遍历中,排在被删除节点后面的第一个节点)替代该节点;此时孩子节点为空,相当于是在子树中删除了这个节点,对该节点继续运用这三条规则。

实际上替换后,孩子节点只会符合前两种情况,不可能会出现第三种情况。因为孩子节点是根节点中序遍历后的直接后驱,说明该孩子节点必为叶子节点或者没有左子树(若有左子树,那么会先访问左子树,在左子树中查找到一个符合上述描述的节点)。

6. 二叉排序树的查找效率分析

        二叉排序树的查找效率,主要依赖于树的高度。若二叉排序树的左右子树高度之差的绝对值小于等于1,此时效率最高,平均查找长度为:

O(\log _{_{2}}n)

若只有左子树或者右子树,那么此时效率最低,平均查找长度为

O(n)

        可以将二叉排序树和二分法查找对应起来,效率最高时,相当于以序列的最中心节点作为起始节点开始查找,并且每次确定下一个元素时,都是以最中心位置来查找。效率最低时,相当于对有序序列进行顺序查找,一个一个进行比对。

二、平衡二叉树(AVL)

1. 平衡二叉树的定义

        在二叉排序树的前提上,左右子树的高度之差绝对值小于等于1。左子树和右子树的高度之差称为平衡因子。

平衡二叉树的平衡因子只可能为{-1,0,1}

2. 平衡二叉树的插入

        插入和二叉排序树一样,在插入结束后,可能会导致二叉树不平衡,此时需要对二叉树进行平衡调整。

        首先找到最小不平衡子树,根据不平衡子树的状态,选择如下方法进行调整:

最小不平衡子树的寻找方法:从插入的节点开始往上,找到的第一颗不平衡的子树(平衡因子绝对值大于1的子树)

  1. 右单旋转。在A节点的左孩子的左子树上插入一个节点,导致的不平衡。
    A的左孩子为B,在B的左子树上插入一个新的节点导致的不平衡。
    调整方法:B节点右旋替代A的位置。
  2. 左单旋转。在A节点的右孩子的右子树上插入的一个节点,导致的不平衡。
    A的右孩子为B,在B的右子树上插入一个新的节点导致的不平衡。
    调整方法:B节点左旋替代A的位置。
  3. 先左旋后右旋。在A节点的左孩子的右子树上插入一个新的节点,导致的不平衡。
    A的左孩子为B,B的右孩子为C,在C的子树上插入一个新的节点导致的不平衡。
    调整方法:C节点先左旋替代B的位置,再右旋替代A的位置。
  4. 先右旋后左旋。在A节点的右孩子的左子树上插入一个新的节点,导致的不平衡。
    A的右孩子为B,B的左孩子为C,在C的子树上插入一个新的节点导致的不平衡。
    调整方法:C节点先右旋替代B的位置,再左旋替代A的位置。

关于旋转,将下面(B节点)的节点往上面移动,上面的节点(A节点)顺势向下移动,两节点的关系互换(例如:原先是父节点和左孩子-->变为右孩子和父节点),此时A节点会空缺一个子节点,B节点会多出一个子节点,将这个多出的节点插入到A节点空缺的位置上,一次旋转就完成。

3. 平衡二叉树的删除

        先用二叉排序树的删除方法删除掉节点,然后在对齐平衡性进行调整。从删除的节点向上找到第一个不平衡点A,从改点向下延伸两个节点B,C;B是A的最高子树节点,C是B的最高子树节点。根据上面的方法以及ABC的关系,选择对于的选择进行调整。

4. 平衡二叉树的查找效率

       O(\log _{_{2}}n)

三、红黑树

3.1红黑树的定义

        对于平衡二叉树,插入和删除对树的调整非常频繁,为此在平衡二叉树上放宽平衡标准,引入红黑树。红黑树是满足以下条件的二叉排序树:

  1. 节点颜色只能为红或者黑。
  2. 根节点为黑色。
  3. 叶子节点为黑色。
  4. 不允许有两个连续的红色节点,可以有连续的黑色节点。
  5. 对每个节点,从该节点到任意一个叶子节点所包含的黑色节点数相同。

叶子节点是外节点(空节点NULL),相当于在原有的二叉树的每个叶子节点,接上两个空的子节点。

        结论一:从根节点到叶子节点的最长路径长度不大于最短路径的两倍。

        最长路径的情况下是红黑节点交替出现,此时黑色节点数等于红色节点数;最短路径是没有红色节点全都为黑色节点。因为性质5:对每个节点,从该节点到任意一个叶子节点所包含的黑色节点数相同。所以最长路径是两倍的黑色节点数=两倍的最短路径。

        结论二:有n个内部节点的红黑树高度小于等于2\log _{_{2}}(n+1)

2. 红黑树的插入

        插入方法和二叉排序树一样,插入结束后需要对其平衡性进行调整,通过重新着色和选择来完成。设新插入节点为z节点,插入过程如下:

  1. 根据二叉排序树的插入方法进行插入,z节点置为红色。
  2. 若z节点为根节点,则染色为黑色。
  3. 若z节点不为根节点,其父节点为黑色,则无需调整。
  4. 若z节点不为根节点,其父节点为红色,则分为以下两种情况:
    情况1:z的叔节点y是黑色。
    情况2:z的叔节点y是红色。
    调整方法:
    情况1:z和父节点z.p都同为左孩子(右孩子),那么z.p选择替换其父节点z.p.p,然后z.p染黑,z.p.p染红;z和父节点z.p都为不同的方位的孩子,那么z先旋转替代父节点z.p,再旋转替代爷节点z.p.p。
    情况2:z.p和y节点染黑,z.p.p染红,然后将z.p.p作为新插入节点,重复上面的步骤。

四、B树

 1. B树的定义

         m阶B树是所有节点的平衡因子均等于0的m路平衡查找树。满足以下特性:

  1. 树中每个节点至多有m棵子树,至多有m-1个关键字。
  2. 若根节点不是叶子节点,则至多有两棵子树,至多一个关键字。
  3. 除了根节点以外,所有非叶子节点至少有$\lceil m/2 \rceil$棵子树(向上取整),$\lceil m/2 \rceil$-1个关键字。
  4. 所有非叶子节点的构造如下(长度可变,下例为方便使用特定的长度)
    nP_{0}K_{0}P_{1}K_{1}P_{2}
     

    n是关键字的个数,K的个数。
    K是关键字,按增序排列。
    P是树枝,即指向子树的指针,P指向的子树中的所有节点,都小于其右边的关键字,且大于左边的关键字。

2. B树的查找

        和二叉排序树的查找方式一样,只是每个节点有多个分路。先在节点内找相等的节点,不存在则进入对应的子树中继续查找,直到找到相等的节点或者查找失败为止。

3. B树的高度

        首先,B树的高度不包括外节点。若n≥1,则对一颗包含n个关键字,m阶的B树:

  1. 让每个节点关键字达到最多。每个节点则最多有m棵子树,m-1个关键字。那么在高度为h的m阶B树中关键字满足:n\leqslant (m-1)(1+m+m^{2}+...+m^{h-1})=m^{h}-1
    即 h\geq \log _{m}(n+1)
  2. 让每个节点关键字最少。第一层1个节点,第二层2个节点,除根节点外,每个节点有$\lceil m/2 \rceil$棵子树,第h+1层有2(\lceil m/2 \rceil)^{h-1},h+1层是外节点,对于关键字个数为n的B树,叶节点即查找失败的节点为n+1,满足:n+1\geq 2(\lceil m/2 \rceil)^{h-1}
    h\leq \log _{\lceil m/2 \rceil}((n+1)/2)+1

高度h的范围即:

\log _{m}(n+1)\leq h \leq \log _{\lceil m/2 \rceil}((n+1)/2)+1

4. B树的插入

  1. 定位。利用上述B树的查找方法,找到需要插入的节点。
  2. 插入。如果节点中关键字没满,可以直接插入;如果关键字已满,先插入关键字,再进行分裂。
  3. 分裂。将节点中心位置的关键字作为一个新的节点P,左右两侧分裂成两个新的节点,并插入到节点P上,节点P则插入到父节点中;如果P的插入导致了父节点中关键字超员,则继续对父节点进行分裂,直到这个过程传递到根节点为止,使得树的高度加1。

5. B树的删除

        若删除的关键字在终端节点。

  1. 删除关键字后,节点中关键字个数依然满足\geq \lceil m/2 \rceil,则可以直接删除。
  2. 不满足条件一 ,如果兄弟节点够借(兄弟节点删掉一个关键字,依然满足B树的性质)那么就向兄弟节点借一个关键字。将被删除的关键字的父节点中的一个关键字下移,借来的兄弟顶替父节点中空缺的位置。
  3. 不满足条件一,且兄弟节点不够借,则需要合并节点。删除关键字后,将对于的父节点中的关键字下移。

五、B+树

1. B+树的定义

        一棵m阶B+树应该满足:

  1. 每个分支节点最多有m棵子树。
  2. 根节点不是叶子节点时,至少有两棵子树;其他节点至少有\lceil m/2 \rceil棵子树。
  3. 节点的关键字个数等于子树个数
  4. 所有叶节点包含全部的关键字,以增序排列(线性链表)。
  5. 所有分支节点仅包含他的子节点中关键字的最大值,分支节点上的关键字只起到索引作用。

2. B+树的查找

        查找和B树类似,只是在分支节点查到相等的节点时并不停下,而是继续向下,直到叶节点上的关键字位置。所以在B+树上的查找,每次都是从根节点到叶子节点的一条路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值