18.平衡二叉树(AVL树)、多路树查找(B树)概念

/*
8.7 平衡二叉树(AVL树)
平衡二叉树(Self-Balancing SearchTree或Height-Balanced Binary Search Tree),是一种二叉排序树,
其中每一个节点的左子树和右子树的高度差至多等于1。
有两位俄罗斯数学家G.M.Adelson-Velskii和E.M.Landis在1962年共同发明一种解决平衡二叉树的算法,所以
有不少资料中也称这样的平衡二叉树为AVL树。
8.7.1 平衡二叉树实现原理
平衡二叉树构建的基本思想就是在构建二叉排序树的过程中,每当插入一个结点时,先检查是否因插入而破坏了
平衡性,若是,则找出最小不平衡树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各节点之间的链接关系,
进行相应的旋转,使之成为新的平衡子树。
*/

/*
8.7.2 平衡二叉树实现算法
ok,有了这么多的准备工作,我们可以来讲解代码了。首先是需要改进二叉排序树的结点结构,增加一个bf,用来
存储平衡因子。
*/
//二叉树的二叉链表结点结构定义
//结点结构
typedef struct BiTNode
{
    //结点数据
    int data;
    //结点的平衡因子
    int bf;
    //左右孩子指针
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
//然后,对于右旋操作,我们的代码如下。
/*
对以P为根的二叉排序树作右旋处理,处理之后p指向新的树根节点,即旋转处理之前的左子树的根结点
*/
void R_Rotate(BiTree *P)
{
    BiTree L;
    //L指向P的左子树根节点
    L=(*P)->lchild;
    //L的右子树挂接为P的左子树
    (*P)->lchild = L->rchild;
    L->rchild = (*P);
    //P指向新的根结点
    *P = L;
}

/*
左旋操作代码如下
对以P为根的二叉排序树作左旋处理,处理之后P指向新的树根结点,即旋转处理之前的右子树的根结点0
*/
void L_Rotate(BiTree *P)
{
    BiTree R;
    //R指向P的右子树根结点
    R = (*P)->rchild;
    //R的左子树挂接为P的右子树
    (*P)->rchild = R->lchild;
    R->lchild = (*P);
    //P指向新的根结点
    *P = R;
}
//上边的代码和右旋是对称的,可以查看p594 图8-7-9对右旋操作的解释

/*
现在我们来看左平衡旋转处理的函数代码
*/

#define LH +1   //左高
#define EH 0    //等高
#define RH -1   //右高
//对以指针T所指结点为根的二叉树作左平衡旋转处理。 本算法结束时,指针T指向新的根节点
void LeftBalance(BiTree *T)
{
    BiTree L,Lr;
    //L指向T的左子树根节点
    L = (*T)->lchild;
    switch(L->bf)
    {
        //检查T的左子树的平衡度,并作相应平衡处理
        //新节点插入在T的左孩子的左子树上,要作单右旋处理
        case LH:
            (*T)->bf = L->bf = EH;
            R_Rotate(T);
            break;
        //新结点插入在T的左孩子的右子树上,要作双旋处理
        case RH:
            //Lr指向T的左孩子的右子树根
            Lr = L->rchild;
            //修改T及其左孩子的平衡因子
            switch (Lr->bf)
            {
                case LH: (*T)->bf = RH;
                    L->bf = EH;
                    break;
                case EH: (*T)->bf = L->bf = EH;
                    break;
                case RH: (*T)->bf = EH;
                    L->bf = LH;
                    break;
            }
            Lr->bf = EH;
            //对T的左子树作左旋平衡处理
            L_Rotate(&(*T)->lchild);
            //对T作右旋平衡处理
            R_Rotate(T);
    }
}

/*
8.8 多路查找树(B树)
B树和B+树 书上只给出了一些概念描述和图片,并没有给出实现的代码

我们之前谈的树,都是一个结点可以右多个孩子,单它自身只存储一个元素。二叉树限制更多,结点最多只能有
两个孩子。
一个结点(父节点也叫双亲节点)只能存储一个元素,在元素非常多的时候,就使得要么树的度非常大(结点拥有
子树的个数的最大值),要么树的高度非常大,甚至两者都必须足够大才行。这就使得内存读取存取外存次数非常多,
这显然成了时间效率上的瓶颈,这迫使我们要打破每一个结点只存储一个元素的限制,为此引入了多路查找树的概念。

多路查找树(muitl-way search tree),其每一个结点的孩子数可以多于两个,且每一个结点处可以存储多个元素。
由于它是查找树,所有元素之间存在某种特定的排序关系。
在这里,每一个结点可以存储多少个元素,以及它的孩子数的多少是非常关键的。为此,我们讲解它的4种特殊形式:
2-3树、2-3-4树、B树、B+树。
B树的数据结构就是为内外存的数据交互准备的。

一棵m阶的B+树和m阶的B树差异在于:
    1.有n棵子树的结点中包含有n个关键字。
    2.所有的叶子结点包含全部关键字的信息,及指向含这些关键字记录的指针,叶子结点本身依关键字的大小自小
        而大顺序链接;
    3.所有分支结点可以看成索引,结点中仅含有其子树中的最大(或最小)关键字。
*/
原文地址:https://www.cnblogs.com/go-ahead-wsg/p/13268440.html