平衡二叉排序树(AVL树)

目录

一、AVL树简介

1.1 AVL树具有的性质

1.2 平衡因子

1.3 失衡类型及调整方法

二、算法

2.1 初始化

2.2 查找插入位置

2.3 插入新结点

2.4 更新所有结点的平衡因子

2.5 调整算法

三、总结


一、AVL树简介

1.1 AVL树具有的性质

1、左子树与右子树的高度之差的绝对值小于等于1。

2、左子树和右子树也是平衡二叉排序树。

1.2 平衡因子

平衡因子(balance factor):结点的左子树深度与右子树深度之差。


1.3 失衡类型及调整方法

1、LL型

2、LR型

 

3、RR型

4、RL型

 


二、算法

2.1 初始化

{
    AVLTree S, A, FA, p, fp, B, C;

    /* 生成待插结点 */
    S = (AVLTree)malloc(sizeof(AVLTNode));
    S->key = K;
    S->lchild = S->rchild = NULL;
    S->bf = 0;

    if (*avlt == NULL) {
        *avlt = S;
        return;
    }

    /* 初始化各指针 */
    A = *avlt;
    FA = NULL;
    p = *avlt;
    fp = NULL;
}

2.2 查找插入位置

while (p != NULL) { /* 因为插入位置最终为叶结点 */
    if (p->key == K) { /* 若存在关键字等于key的元素,则放弃插入 */
        free(S);
        return;
    }

    if (p->bf != 0) { /* 使A为最低层失衡结点 */
        A = p;
        FA = fp;
    }

    fp = p;
    if (K < p->key)
        p = p->lchild;
    else
        p = p->rchild;
}

2.3 插入新结点

if (K < fp->key)
    fp->lchild = S;
else
    fp->rchild = S;

2.4 更新所有结点的平衡因子

/* 确定旋转点B,同时更新A的平衡因子 */
if (K < A->key) {
    B = A->lchild;
    A->bf = A->bf + 1;
} else {
    B = A->rchild;
    A->bf = A->bf - 1;
}

/* 更新B到S的路径上各结点的平衡因子(原值均为0)*/
p = B;
while (p != S) {
    if (K < p->key) {
        p->bf = 1;
        p = p->lchild;
    } else {
        p->bf = -1;
        p = p->rchild;
    }
}

2.5 调整算法

1、LL型

if (A->bf == 2 && B->bf == 1) {
    /* 顺时针旋转 */
    B = A->lchild;
    A->lchild = B->rchild;  //B的右子树成为A的左子树
    B->rchild = A;          //A成为B的右子树
    
    /* 更新平衡因子 */
    A->bf = 0;
    B->bf = 0;
    
    /* 更新结点关系 */
    if (FA == NULL)
        *avlt = B;
    else if (A == FA->lchild)
        FA->lchild = B;
    else
        FA->rchild = B;
}

2、LR型

if (A->bf == 2 && B->bf == -1) {
    B = A->lchild;
    C = B->rchild;
    /* 逆时针旋转 + 顺时针旋转 */
    B->rchild = C->lchild;
    A->lchild = C->rchild;
    C->lchild = B;
    C->rchild = A;

    /* 更新平衡因子 */
    if (S->key < C->key) {
        A->bf = -1;
        B->bf = 0;
        C->bf = 0;
    } else if (S->key > C->key) {
        A->bf = 0;
        B->bf = 1;            
        C->bf = 0;
    } else {
        A->bf = 0;
        B->bf = 0;
    }

    /* 更新结点关系 */
    if (FA == NULL)
        *avlt = C;
    else if (A == FA->lchild)
        FA->lchild = C;
    else
        FA->rchild = C;
}

3、RR型

if (A->bf == -2 && B->bf == -1) {
    /* 逆时针旋转 */
    B = A->rchild;
    A->rchild = B->lchild;
    B->lchild = A;

    /* 更新平衡因子 */
    A->bf = 0;
    B->bf = 0;

    /* 更新结点关系 */
    if (FA == NULL)
        *avlt = B;
    else if (A == FA->lchild)
        FA->lchild = B;
    else
        FA->rchild = B;
}

4、RL型

if (A->bf == -2 && B->bf == 1) {
    B = A->rchild;
    C = B->lchild;
    /* 顺时针旋转 + 逆时针旋转 */
    B->lchild = C->rchild;
    A->rchild = C->lchild;
    C->lchild = A;
    C->rchild = B;

    /* 更新平衡因子 */
    if (S->key < C->key) {
        A->bf = 0;
        B->bf = -1;
        C->bf = 0;
    } else if (S->key > C->key) {
        A->bf = 1;
        B->bf = 0;
        C->bf = 0;
    } else {
        A->bf = 0;
        B->bf = 0;
    }

    /* 更新结点关系 */
    if (FA == NULL)
        *avlt = C;
    else if (A == FA->lchild)
        FA->lchild = C;
    else
        FA->rchild = C;
}

三、总结

平衡二叉排序树插入操作的算法思想:

1、查找插入位置,同时记录离插入位置最近的可能失衡结点A;

2、插入新结点S;

3、确定旋转点B,同时更新A的平衡因子;

4、更新B到S的路径上各结点的平衡因子(原值必为0,否则A将下移);

5、根据A、B的平衡因子判断是否失衡以及失衡类型,并做相应处理。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值