AVL是一种平衡二叉树,它通过对二叉搜索树中的节点进行旋转使得二叉搜索树达到平衡。AVL在所有的平衡二叉搜索树中具有最高的平衡性。

定义

平衡二叉树或者为空树或者为满足如下性质的二叉搜索树:

  1. 左右子树的高度之差绝对值不超过1
  2. 左右子树仍然为平衡二叉树

定义平衡因子 BF(x) = x的左子树高度 - x的右子树的高度。平衡二叉树的每个节点的平衡因子只能为-1, 0, 1.

维持平衡思想

若二叉树当前为平衡状态,此时插入/删除一个新的节点,此时有可能造成二叉树不满足平衡条件,此时需要通过对节点进行旋转来使得二叉树达到平衡状态。从被插入/删除的节点开始向上查找,找到第一个不满足 |BF| <= 1的祖先节点P,此时对P和P的子节点(或P的子节点的子节点)进行旋转(可能分为下面的四种情况)。

旋转

(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型处理成平衡型。

实现(c++)

#include<iostream>
using namespace std;
#define MAX(a, b) a > b? a:b
struct TreeNode{
int data;
TreeNode* child[2];
int size;
int height;
int count;
TreeNode(int val){
data = val;
size = count = height = 1;
child[0] = child[1] = NULL;
}
void Update(){
size = count;
height = 1;
if (child[0]){
size += child[0]->size;
height = MAX(height, 1 + child[0]->height);
}
if (child[1]){
size += child[1]->size;
height = MAX(height, 1 + child[1]->height);
}
}
}; struct AVL{
TreeNode* root;
AVL() :root(NULL){}; int GetHeight(TreeNode* node){
if (!node)
return 0;
return node->height;
}
int GetSize(TreeNode* node){
if (!node)
return 0;
return node->size;
} //注意这里使用指针的引用
void Rotate(TreeNode*& node, int dir){
TreeNode* ch = node->child[dir];
node->child[dir] = ch->child[!dir];
ch->child[!dir] = node;
node->Update();
node = ch;
}
void Maintain(TreeNode*& node){
if (!node){
return;
}
int bf = GetHeight(node->child[0]) - GetHeight(node->child[1]);
if (bf >= -1 && bf <= 1){
return;
}
if (bf == 2){
int bf2 = GetHeight(node->child[0]->child[0]) - GetHeight(node->child[0]->child[1]);
if (bf2 == 1){ //左左旋转
Rotate(node, 0);
}
else if (bf2 == -1){ //左右旋转
Rotate(node->child[0], 1);
Rotate(node, 0);
}
}
else if (bf == -2){
int bf2 = GetHeight(node->child[1]->child[0]) - GetHeight(node->child[1]->child[1]);
if (bf2 == 1){ //右左旋转
Rotate(node, 1);
}
else if (bf2 == -1){ //右右旋转
Rotate(node->child[1], 0);
Rotate(node, 1);
}
} }
void Insert(TreeNode*& node, int val){
if (!node){
node = new TreeNode(val);
}
else if (node->data == val){
node->count++;
}
else{
int dir = node->data < val;
Insert(node->child[dir], val);
}
//维持树的平衡
Maintain(node);
//更新节点
node->Update();
} //注意参数为指针的引用
void Delete(TreeNode*& node, int val){
if (!node){
return;
}else if (node->data == val){
if (node->child[0] && node->child[1]){
int dir = GetHeight(node->child[0]) < GetHeight(node->child[1]);
//将子树中较高的那棵,旋转
Rotate(node, dir);
//递归调用delete,直到叶子节点才进行真正的删除
Delete(node->child[! dir], val);
}
else{
TreeNode* tmp_node = NULL;
if (node->child[0]){
tmp_node = node->child[0];
}
else if (node->child[1]){
tmp_node = node->child[1];
}
delete node;
node = tmp_node; //使用引用
}
}
else{
int dir = node->data < val;
Delete(node->child[dir], val);
}
Maintain(node); //维持平衡
node->Update(); //更新节点
}
int GetKth(TreeNode* node, int k){
while (node){
if (! node->child[0]){
if (k <= node->count){
return node->data;
}
else{
k -= node->count;
node = node->child[1];
}
}
else{
if (node->child[0]->size < k && node->child[0]->size + node->count >= k){
return node->data;
}
else if (node->child[0]->size > k){
node = node->child[0];
}
else{
k -= (node->child[0]->size + node->count);
node = node->child[1];
}
}
}
return -1;
}
};

参考: 
平衡树 balanced binary tree (AVL tree)  
AVL树 模板

AVL 平衡树的更多相关文章

  1. 实现Avl平衡树

    实现Avl平衡树   一.介绍 AVL树是一种自平衡的二叉搜索树,它由Adelson-Velskii和 Landis于1962年发表在论文<An algorithm for the organi ...

  2. Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现

    AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...

  3. 数据结构学习-AVL平衡树

    环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...

  4. AVL平衡树的插入例程

    /* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...

  5. AVL平衡树(非指针实现)

    看了网上三四篇博客,学习了AVL树维护平衡的方式.但感觉他们给出的代码都有一点瑕疵或者遗漏,懂得了思想之后,花了一些时间把他们几篇的长处结合起来,没有使用指针,实现了一下.每个小逻辑功能都抽象成了函数 ...

  6. 数据结构——AVL平衡树

    1.是二叉搜索树(Binary Search Tree) 2.树和所有左右子树高度之差为-1,0,1 平衡因子(balance factor) =右子树高度-左子树高度 平衡化旋转: 1.从插入位置向 ...

  7. My implementation of AVL tree

    C++实现的avl平衡树 #include <stdlib.h> #include <time.h> #include <string.h> #include &l ...

  8. [SinGuLaRiTy] 平衡树

    [SinGuLaRiTy-1009] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 二叉查找树 二叉查找树是指具有下列性质的非空二叉树: ⑴ ...

  9. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树.   2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1).   也就是说,AVL树,本质上 ...

随机推荐

  1. win10计算机打开不要是“快速访问”功能?

    win10的文件夹选项中---常规--最上端调整

  2. npm常用命令汇总

    npm是一个node包管理和分发工具,已经成为了非官方的发布node模块(包)的标准. 有了npm,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. 1.npm install ...

  3. 关于Cocos2d-x中类与类之间调用彼此方法的机制

    1.一般情况下都是把需要实例化的对象类的头文件包含到一个GameController.h中,再在GameController.cpp文件里面去使用各种对象类的方法来实现游戏的逻辑. 2.还有的时候会把 ...

  4. 写给大忙人的JavaSE 8 - 学习

    前面有提到过lambda和函数式接口,但是JavaSE 8 除了这两个新特性之后还提供了很多有用的东西.例如Stream. 摸索了几天,终于弄明白Stream的应用了. 先推荐一篇文章:Java 8 ...

  5. strcpy、strncpy、memcpy的区别

    一.strcpy.strncpy区别 struct gpInfo { char gpcode[9]; char gpName[50]; }; string gpstr = "SZ000001 ...

  6. Zookeeper leader选举

    让我们分析如何在ZooKeeper集合中选举leader节点.考虑一个集群中有N个节点.leader选举的过程如下: 所有节点创建具有相同路径 /app/leader_election/guid_ 的 ...

  7. unity3d绘画手册-------地形各个参数解释

    关于Unity3D是什么.我就不多做解释了.由于工作原因,该系列原创教程不定期更新.每月必然有更新.谢谢各位. Unity地形:: 新建地形: <ignore_js_op> 如图在菜单中新 ...

  8. Python的类和函数的魔法

    class CustomClass: def customFun(self, id): print("fun_1",id ) if __name__ == '__main__': ...

  9. ubuntu安裝 R RStudio

    sudo apt--i386.deb ref: http://blog.csdn.net/lichangzai/article/details/39376117

  10. 经常使用的CSS Hack技术集锦

    来源:http://www.ido321.com/938.html 一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致同样的CSS输出的页面效果不同,这就须要CSS Ha ...