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树,本质上 ...
随机推荐
- win10计算机打开不要是“快速访问”功能?
win10的文件夹选项中---常规--最上端调整
- npm常用命令汇总
npm是一个node包管理和分发工具,已经成为了非官方的发布node模块(包)的标准. 有了npm,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. 1.npm install ...
- 关于Cocos2d-x中类与类之间调用彼此方法的机制
1.一般情况下都是把需要实例化的对象类的头文件包含到一个GameController.h中,再在GameController.cpp文件里面去使用各种对象类的方法来实现游戏的逻辑. 2.还有的时候会把 ...
- 写给大忙人的JavaSE 8 - 学习
前面有提到过lambda和函数式接口,但是JavaSE 8 除了这两个新特性之后还提供了很多有用的东西.例如Stream. 摸索了几天,终于弄明白Stream的应用了. 先推荐一篇文章:Java 8 ...
- strcpy、strncpy、memcpy的区别
一.strcpy.strncpy区别 struct gpInfo { char gpcode[9]; char gpName[50]; }; string gpstr = "SZ000001 ...
- Zookeeper leader选举
让我们分析如何在ZooKeeper集合中选举leader节点.考虑一个集群中有N个节点.leader选举的过程如下: 所有节点创建具有相同路径 /app/leader_election/guid_ 的 ...
- unity3d绘画手册-------地形各个参数解释
关于Unity3D是什么.我就不多做解释了.由于工作原因,该系列原创教程不定期更新.每月必然有更新.谢谢各位. Unity地形:: 新建地形: <ignore_js_op> 如图在菜单中新 ...
- Python的类和函数的魔法
class CustomClass: def customFun(self, id): print("fun_1",id ) if __name__ == '__main__': ...
- ubuntu安裝 R RStudio
sudo apt--i386.deb ref: http://blog.csdn.net/lichangzai/article/details/39376117
- 经常使用的CSS Hack技术集锦
来源:http://www.ido321.com/938.html 一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致同样的CSS输出的页面效果不同,这就须要CSS Ha ...