高阶数据结构之AVL树

AVL树的插入实现

AVL树是二叉平衡树,即在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。


1. 搜索树

二叉搜索树

特征:
任取树中的结点,要求结点的左子树中的所有key全部小于结点的key
结点的右子树中的所有key全部大于结点的key

1.前置约束基本没有
2.compare(TreeMap的key或者treeSet的元素,必须具有compare的能力(Comparable OR Comparator))
3.搜索树时间复杂度最坏情况下是O(n)——(最坏情况,退化成单支树)
一般提到搜索树,都是说平衡搜索树(高度不会差太多),时间复杂度为O(log(n)) 插入/删除/查找(找到位置直接操作)
而修改平衡搜索树(key)一般采用:先删除(删除原来的val),后插入(插入修改后的数据),不能破坏树的特性


2.平衡搜索树的具体实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0BBSEcph-1601206926346)(en-resource://database/848:1)]

1.二叉平衡搜索树——AVL树

AVL的树的要求
1.二叉树
2.搜索树
3.任取树的结点,该结点的左右子树高度差不超过1(任取结点,BF in(-1,0,1))
高阶数据结构之AVL树_第1张图片
(1)关于AVL树的查找——和平衡树查找方式一致
(2)关于AVL树的插入
插入之前:整棵树满足AVL的特征
插入期间:AVL的特征可能会被临时性的破坏掉,所有插入过程中,我们要负责修复AVL的特征
插入之后:整棵树仍满足AVL的特征
高阶数据结构之AVL树_第2张图片


前提定义:
高阶数据结构之AVL树_第3张图片

插入过程:
1.完全按照普通搜索树的方式插入
遇到重复的数怎么办?
搜索树中就不允许key重复,所以会插入失败。

2.标注+更新平衡因子
(1).新插入的结点,平衡因子一定是0
(2).新结点的父节点(parent)的BF需要更新
(3).parent.BF=? 需要看cur == parent.left(parent.BF=parent.BF+1) OR cur == parent.right(parent.BF=parent.BF-1)
(4).parent.BF变化的完整表

之前满足AVL时parent.BF的值 left or right parent.BF之后的值
-1 left 0
-1 right -2
0 left 1
0 right -1
1 left 2
1 right 0

(5).考虑两个点:
《1》parent的BF值是否破化了AVL树的特征;
《2》H(parent)是否发生了变化(是否增加一)
情况一:
在这里插入图片描述
情况二:
高阶数据结构之AVL树_第4张图片
第三种情况:
高阶数据结构之AVL树_第5张图片
如果是第三种情况,需要进行失衡调整,调整方式又分为:
1.左左失衡
高阶数据结构之AVL树_第6张图片

2.左右失衡
高阶数据结构之AVL树_第7张图片
3.右右失衡

4.右左失衡
(等我闲了我再画)


关于树的旋转

二叉搜索树在失去平衡之后,可以通过旋转的方式,来解决不平衡
树的旋转目标是 :旋转完之后,仍然是搜索树

情况 旋转前 左旋/右旋 旋转后
左左失衡 高阶数据结构之AVL树_第8张图片 右旋 高阶数据结构之AVL树_第9张图片
左右失衡 高阶数据结构之AVL树_第10张图片 1.对失衡结点的左孩子左旋,使其变为左左失衡 2.针对失衡结点右旋 高阶数据结构之AVL树_第11张图片
右右失衡 左旋
右左失衡 1.首先对失衡因子的右孩子,右旋 2.然后失衡因子,左旋

1.针对失衡结点右旋

高阶数据结构之AVL树_第12张图片

已知:Key(甲) 调整为:
高阶数据结构之AVL树_第13张图片

伪代码:

void rightRotate(Node parent){
    Node parentOfParent=parent.parent;//假设parent不是根
    Node cur = parent.left;
    Node rootOf乙子树=cur.right;
    cur.right=parent;
    parent.parent=cur;
    parent.left=rootOf乙子树;
    if(rootOf乙子树!=null){
       rootOf乙子树.parent=parent;
    }
    修改parentOfParent的孩子变成cur,但需要考虑以下情况:
    1.parent原来不是根(parentOfParent!=null)
    2.分清楚parent原来是parentOfParent的左边还是右边
}

左旋

代补充!


关于失衡修复后平衡因子的计算

  • 当左左失衡的情况下,进行右旋解决失衡问题,最终,结点的平衡因子:
    BF(parent)=BF(cur)=0
  • 当左右失衡的情况下,进行先左旋,后右旋解决失衡问题,最终,结点的平衡因子:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9nHLs3W-1601206926362)(en-resource://database/894:1)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TSVyY94D-1601206926363)(en-resource://database/896:1)]
旋转前破坏因子高度 旋转后
BF(cc)==1:破环源来自乙子树 H(乙)=x,H(丙)=x-1 H(甲)=H(乙)=H(丁)=x,H(丙)=x-1; BF( c) =0,BF(cc)=0,BF( p)=-1
BF(cc)==-1:破环源来自丙子树 H(丙)=x,H(乙)=x-1 BF( c )=1,BF(cc)=0,BF( p)=0
BF(cc)==0:破环源就是cc H(乙)=H(丙)=x=0 BF( c)=0,BF(cc)=0,BF( p)=0

AVL树的实现

1.按照普通搜索树的插入方式进行插入
2.插入之后,调整收到影响的结点的平衡因子
记,需要调整BF的结点为parent

  • 如果破坏源来自parent的left,则BF(parent)++
  • 如果破坏源来自parent的right,则BF(parent)- -

3.得到调整BF后的结果
高阶数据结构之AVL树_第14张图片

4.四种失衡状况

  • 1.左左失衡——对失衡结点右旋
  • 2.左右失衡——先失衡结点的left左旋,再失衡结点右旋
  • 3.右右失衡——对失衡结点左旋
  • 4.右左失衡——先失衡结点的right右旋,再失衡结点左旋

设计的AVL树的结构:

高阶数据结构之AVL树_第15张图片


区分左左or左右
高阶数据结构之AVL树_第16张图片

区分右右or右左

左旋
高阶数据结构之AVL树_第17张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t2PUTWaj-1601206926368)(en-resource://database/912:1)]
右旋上面有


验证avl树

1.是不是二叉树(结构规定了肯定是二叉树)
2.验证是否为二叉搜索树(中序遍历结构有序)
3.是不是AVL树

  • 是不是树中,每个结点BF in(-1,0,1)
  • 验证每个结点BF是不是存储正确数值(当前结点的BF是不是等于它左子树BF-右子树BF)

AVL树的时间复杂度:

查找O(log(n))
插入O(log(n))
插入过程比较复杂,如果想实现线程安全版本的AVL树,很复杂(好吧我是菜鸡QAQ!!)

你可能感兴趣的:(高阶数据结构之AVL树)