当前位置: 首页 > news >正文

(转)平衡树

转自:http://hi.baidu.com/dongaxis/item/ff10fdb41d26b79f19469784

平衡树

二叉树

左子树都小于根节点,右子树都大于根节点。可以动态维护这棵树(因为是树结构,可以有限步完成插入),所以是动态查找算法。时间复杂度为O(logn)在46.5%的情况下,需要把二叉树平衡化成“平衡二叉树”。

平衡二叉树

平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:

  (1)左右子树深度之差的绝对值不超过1;

  (2)左右子树仍然为平衡二叉树.

 平衡因子

平衡因子bf=左子树深度-右子树深度,每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。增加一个元素后,平衡二叉树有可能变成不平衡了,所以需要旋转平衡调整。如图所示为平衡树和非平衡树示意图:

   

 

平衡二叉树算法思想

若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。

 (1)LL型平衡旋转法

由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。

(2)RR型平衡旋转法

由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。


(3)LR型平衡旋转法

由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理。

  如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。

(4)RL型平衡旋转法  

由于在A的右孩子C的左子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将A结点的右孩子C的左子

 



 

树的根结点D向右上旋转提升到C结点的位置,然后再把该D结点向左上旋转提升到A结点的位置。即先使之成为RR型,再按RR型处理。

 如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为RR型,再按RR型处理成平衡型。

平衡化靠的是旋转。参与旋转的是3个节点(其中一个可能是外部节点NULL),旋转就是把这3个节点转个位置。注意的是,左旋的时候p->right一定不为空,右旋的时候p->left一定不为空,这是显而易见的。

如果从空树开始建立,并时刻保持平衡,那么不平衡只会发生在插入删除操作上,而不平衡的标志就是出现bf == 2或者 bf == -2的节点。

插入和删除

插入删除是互为镜像的操作。我们可以采用前面对二叉排序树的删除操作来进行。然后,在删除掉结点后,再对平衡树进行平衡化处理。删除之所以删除操作需要的平衡化可能比插入时次数多,就是因为平衡化不会增加子树的高度,但是可能会减少子树的高度,在有有可能使树增高的插入操作中,一次平衡化能抵消掉增高;在有可能使树减低的删除操作中,平衡化可能会带来祖先节点的不平衡。AVL树体现了一种平衡的美感,两种旋转是互为镜像的,插入删除是互为镜像的操作,没理由会有那么大的差别。实际上,平衡化可以统一的这样来操作:
1、while (current != NULL)修改current的平衡因子。

(1)插入节点时current->bf += (current->data > *p)?1:-1;

(2)删除节点时current->bf -= (current->data > *p)?1:-1;

(3)current指向插入节点或者实际删除节点的父节点,这是普通二叉搜索树的插入和删除操作带来的结果。*p初始值是插入节点或者实际删除节点的data。因为删除操作可能实际删除的不是data。

2、判断是否需要平衡化

if (current->bf == -2)    L_Balance(c_root);

else if (current->bf == 2) R_Balance(c_root);

3、是否要继续向上修改父节点的平衡因子

(1)插入节点时if (!current->bf) break;这时,以current为根的子树的高度和插入前的高度相同。

(2)删除节点时if (current->bf) break;这时,以current为根的子树的高度和删除前的高度相同

4、当前节点移动到父节点,转1。

p = &(current->data); current =current->parent;

转载于:https://www.cnblogs.com/wanglin2011/p/3147060.html

相关文章:

  • FROONT – 超棒的可视化响应式网页设计工具
  • Redis 基本操作(一)
  • grub rescue fix
  • 【转载】Oracle中的各种NAME
  • 非类型的类模板参数
  • Spring IOC理解
  • 【Linux技术】linux之configure,pkg-config和PKG_CONFIG_PATH
  • 观察者设计模式
  • 如何在eclipse中添加android ADT
  • jquery ui 的弹出窗体 dialog 高度会产生变化
  • 使用什么快捷键,关闭、打开、最小化qq聊天窗口
  • Vim Vundle 插件管理器
  • VirtualBox-“please use a kernel appropriate for your cpu”
  • Java项目命名规范
  • 对Python进程进行全解析
  • Angular2开发踩坑系列-生产环境编译
  •  D - 粉碎叛乱F - 其他起义
  • docker-consul
  • idea + plantuml 画流程图
  • Java读取Properties文件的六种方法
  • SQLServer之创建数据库快照
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 程序员最讨厌的9句话,你可有补充?
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 给Prometheus造假数据的方法
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用 Docker 部署 Spring Boot项目
  • 跳前端坑前,先看看这个!!
  • 写给高年级小学生看的《Bash 指南》
  • 移动端唤起键盘时取消position:fixed定位
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • FaaS 的简单实践
  • Hibernate主键生成策略及选择
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #HarmonyOS:Web组件的使用
  • #pragam once 和 #ifndef 预编译头
  • (1)常见O(n^2)排序算法解析
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (js)循环条件满足时终止循环
  • (分布式缓存)Redis分片集群
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转) Android中ViewStub组件使用
  • 、写入Shellcode到注册表上线
  • .net 发送邮件
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • @Repository 注解
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [Android] Implementation vs API dependency
  • [Android]使用Git将项目提交到GitHub
  • [AS3]URLLoader+URLRequest+JPGEncoder实现BitmapData图片数据保存