博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AVL树
阅读量:6615 次
发布时间:2019-06-24

本文共 2786 字,大约阅读时间需要 9 分钟。

1. 概念

  之前的介绍过查找二叉树,在原始数据为有序序列的时候,建立的查找二叉树跟链表别无两样。由于这种情况下的查找二叉树完全倾斜,其平均查找时间和最坏查找时间都是O(n),显然效率很低。

  究其原因,查找二叉树没有有效的机制来维持其的平衡性。我们用平衡因子来表示一个结点左子树和右子树的高度之差,若这个值的绝对值始终不大于1,则称这种查找二叉树树为AVL树,即平衡二叉树。

  显然查找二叉树若是完全的,则它是一种AVL树。

2. 维护平衡性原理

  在插入数据的过程中,当某个结点的平衡因子出现绝对值大于1的情况时,需要通过对原来的二叉树进行旋转操作来维持其性质,根据不同的情况,分成了4中不同的旋转方式:LL,RR,LR,RL,具体解释如下:

以离新插入结点最近的祖先结点为准

  • LL:新结点Y被插入到A的左子树的右子树上

image_1bdham1d1jjb5o9sbg1an31p9c2q.png-22.4kB

  • LR:新结点Y被插入到A的左子树的右子树上

image_1bdhagjdn1mma161ecvlup31ju213.png-24.4kB

  • RR:新结点Y被插入到A的右子树的右子树上

image_1bdhahi2ods1tfnib61l5lfj51g.png-15kB

  • RL:新结点Y被插入到A的右子树的左子树上

image_1bdhanoejvern6b10upn9j8hg37.png-34.9kB

  对于四种旋转方式的具体描述:

image_1bdhb4php2fr1uejkum1jle1g213k.png-45.9kB

image_1bdhb6d4onav121v1nm11q6m4ta41.png-61.6kB

3. 代码实现

  • 定义AVL树的类型:
int unbalanced = FALSE;    struct node {        records data;        int bf;        node *lchild;        node *rchild;    };        typedef node * AVL;
  • 实现LL与LR旋转
void LeftRotation(AVL &T, int &unbalanced)    {        AVL gc,lc;        lc = T->lchild;        if(lc->bf == 1) {            T->lchild = lc->rchild;            lc->rchild = T;            T->bf = 0;            T = lc;        } else {            gc = lc->rchild;            lc->rchild = gc->lchild;            gc->lchild = lc;            T->lchild = gc->rchild;            gc->rchild = T;            switch(gc->bf) {                case 1:                    T->bf = -1;                    lc->bf = 0;                    break;                case 0:                    T->bf = lc->bf = 0;                    break;                case -1:                    T->bf = 0;                    lc->bf = 1;            }            T = gc;        }        T->bf = 0;        unbalanced = FALSE;    }
  • 实现RR和RL旋转则和前面类似,大家自己解决吧

  • 插入数据

void AVLInsert(AVL &T,records R,int &unbalanced)    {        if(!T) {            unbalanced = TRUE;            T = new celltype;            T->data = R;            T->lchild = T->rchild = NULL;            T->bf = 0;        } else if (R.key < T->data.key) {            AVLInsert(T->lchild,R,unbalanced);            if(unbalanced) {                switch(T->bf) {                    case -1:                        T->bf = 0;                        unbalanced = FALSE;                        break;                    case 0:                        T->bf = 1;                        break;                    case 1:                        LeftRotation(T,unbalanced);                }             }        } else if (R.key > T->data.key) {            AVLInsert(T->rchild,unbalanced);            if(unbalanced) {                case 1:                    T->bf = 0;                    unbalanced = FALSE;                    break;                case 0:                    T->bf = -1;                    break;                case -1:                    RightRotation(T,unbalanced);            }        } else            unbalanced = FALSE;    }
  • 删除操作(代码类似,自己写)

分三种情况:

  (1)需要删除的节点下并没有其他子节点。

  (2)需要删除的节点下有一个子节点(左或右)。

  (3)需要删除的节点下有两个子节点(既左右节点都存在)。

  对于第三种情况,则要想办法替换其左子树的最右结点(和二叉查找树刚好相反)

转载于:https://www.cnblogs.com/vachester/p/6704460.html

你可能感兴趣的文章
final,finally和finalize之间的区别
查看>>
python 装饰器
查看>>
[辟谣]下蹲猛起来眼前发黑是心脏衰竭的表现?别扯了!
查看>>
paper 96:计算机视觉-机器学习近年部分综述
查看>>
vuex状态管理详细使用方法
查看>>
不要等有了足够的钱才选择去创业!!!
查看>>
手把手教你画嘴巴,以后再也不怕画嘴巴了
查看>>
selenium - webdriver - 截图方法get_screenshot_as_file()
查看>>
linux 命令 — archive
查看>>
强大的jQuery网格插件 ParamQuery
查看>>
io.lettuce.core.RedisCommandTimeoutException: Command timed out
查看>>
种子填充算法描述及C++代码实现
查看>>
Kali渗透测试——快速查找Metasploit的模块
查看>>
如何生成项目的chm文档
查看>>
java封装httpClient工具(支持http和https,包含get和post请求)
查看>>
Rocket - diplomacy - LazyModuleImpLike
查看>>
如何取消OneNote的粘贴来源地址
查看>>
Nginx+Tomcat实现动静分离
查看>>
Exchange Server 2016管理系列课件25.管理安全通讯组
查看>>
考前必背的50个知识点——系统集成项目管理工程师考试
查看>>