AVL 平衡树
AVL是一种平衡二叉树,它通过对二叉搜索树中的节点进行旋转使得二叉搜索树达到平衡。AVL在所有的平衡二叉搜索树中具有最高的平衡性。
定义
平衡二叉树或者为空树或者为满足如下性质的二叉搜索树:
- 左右子树的高度之差绝对值不超过1
- 左右子树仍然为平衡二叉树
定义平衡因子 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 平衡树的更多相关文章
- 实现Avl平衡树
实现Avl平衡树 一.介绍 AVL树是一种自平衡的二叉搜索树,它由Adelson-Velskii和 Landis于1962年发表在论文<An algorithm for the organi ...
- Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现
AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...
- 数据结构学习-AVL平衡树
环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...
- AVL平衡树的插入例程
/* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...
- AVL平衡树(非指针实现)
看了网上三四篇博客,学习了AVL树维护平衡的方式.但感觉他们给出的代码都有一点瑕疵或者遗漏,懂得了思想之后,花了一些时间把他们几篇的长处结合起来,没有使用指针,实现了一下.每个小逻辑功能都抽象成了函数 ...
- 数据结构——AVL平衡树
1.是二叉搜索树(Binary Search Tree) 2.树和所有左右子树高度之差为-1,0,1 平衡因子(balance factor) =右子树高度-左子树高度 平衡化旋转: 1.从插入位置向 ...
- My implementation of AVL tree
C++实现的avl平衡树 #include <stdlib.h> #include <time.h> #include <string.h> #include &l ...
- [SinGuLaRiTy] 平衡树
[SinGuLaRiTy-1009] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 二叉查找树 二叉查找树是指具有下列性质的非空二叉树: ⑴ ...
- 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作
AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上 ...
随机推荐
- Android——ImageView的scaleType属性与adjustViewBounds属性 (转)一
ImageView的scaleType的属性有好几种,分别是matrix(默认).center.centerCrop.centerInside.fitCenter.fitEnd.fitStart.fi ...
- 千兆网口POE供电
一.IEEE802.3af与at标准的解析 链接:http://www.winchen.com.cn/ShowNews2.asp?ID=21&ClassID=1 2003 年6 月,IEEE ...
- shell脚本----if(数字条件,字符串条件,字符串为空)
二元比较操作符,比较变量或者比较数字. 注意数字与字符串的区别. 1.整数比较 -eq 等于,如:if [ "$a" -eq "$b" ] -ne 不等于,如 ...
- Python time & datetime & string 相互转换
#!/usr/bin/env python# -*- coding:utf-8 -*- # @Datetime : 2017/11/23 下午12:37# @Author : Alfred Xue# ...
- 使用html2canvas实现超出浏览器部分截图
之前写过一篇关于 html2canvas如何在元素隐藏的情况下生成截图 的文章,后面发现还有个坑在等着我,就是如果合成图片太大,超出了浏览器的可视区域,那么超出部分是无法截图的.在网上找到了以下方法, ...
- 【F12】网络面板
使用网络面板了解请求和下载的资源文件并优化网页加载性能 (1)网络面板基础 测量资源加载时间 使用 Network 面板测量您的网站网络性能. Network 面板记录页面上每个网络操作的相关信息,包 ...
- 【转】OPenGL MFC绘图
一.简介 GDI是通过设备句柄(Device Context以下简称"DC")来绘图,而OpenGL则需要绘制环境(Rendering Context,以下简称"RC&q ...
- (转)YUV420存储格式
YUV格式有两大类:planar和packed.对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V.对于packed的YUV格式,每个像素点的Y,U ...
- 格局中@null的代码实现方式
布局中通常会用到@null.如RadioButton常用的技巧通过RadioGroup实现Tab,需要设置android:button="@null".如果要在代码中动态创建控件, ...
- linux基础知识的总结
例如以下内容是我对linux基础知识的总结,由于本人在初期学习linux的时候走了不少的弯路,对于基础的掌握耗费了不少的时间,所以为了后来者对linux的基础部分有个清晰的了解,特对基础知识进行了总结 ...