1、定义
平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
(平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。)
平衡因子BF:将二叉树上的结点的左子树的深度减去右子树的深度的值
不平衡状态:当平衡因子BF的绝对之大于1
2、平衡二叉搜索树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。常用算法有红黑树、AVL、Treap、伸展树等。在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log(n)),大大降低了操作的时间复杂度。
3、平衡二叉树的调整
插入新节点时,树的平衡因子发生变化,通过(逆时针)旋转进行调整,使树处于平衡状态。
(1)单选调整
A、单右旋
a、B置为A的位置
b、A置为B的左子树的位置
c、B的左子树置为A的右子树的位置
B、单左旋
a、B置于A的位置
b、A置于B的右子树
c、B的右子树置于A的左子树
(2)双旋调整
双旋调整分类:LL,LR,RR,RL(看插入节点a与被破坏节点b之间的关系,如果a是b的左子树的右子树的节点)。
eg:LR
就是先左旋再右旋,或者先右旋,再左旋。
部分代码实现
代码1、
#include<iostream>
#include<cstdio>
using namespace std;
struct Node{
int data;
int bf;
struct Node *Left,*Right;
};
typedef struct Node* AVL;
//左旋:BF=-2,进行逆时针旋转,使节点的右子树通过左旋变为平衡状态
AVL LeftRot(AVL t)
{
AVL p=t->Right;
t->Right=t->Left;
t->Left=p;
t=p;
return t;
}
//右旋:BF=2,进行顺时针旋转,使节点的左子树通过右旋变为平衡状态
AVL RightRot(AVL t)
{
AVL p=t->Left;
t->Left=p->Right;
p->Right=t;
t=p;
return t;
}
#define LH 1
#define EH 0
#define RH -1
//左旋转平衡:调整节点的左孩子(其他版本有左孩子的处理,即分为LR,LL)
AVL LeftBalance(AVL t)
{
AVL p=t->Left;
switch(p->bf)
{
case LH: //新插入的节点在左子树的左子树上,进行单右旋处理;
t->bf=p->bf=EH; //平衡因子变为0,即旋转后平衡。
t=RightRot(t);
break;
case RH: //新插入的节点在左子树的右子树上,进行双旋处理;
AVL r=p->Right;
switch(r->bf) //修改t和左子树的bf
{
case LH:
t->bf=RH;
p->bf=EH;
break;
case EH:
t->bf=EH;
p->bf=EH;
break;
case RH:
t->bf=EH;
p->bf=LH;
break;
}
r->bf=EH;
t->Left=LeftRot(t->Left);
t=RightRot(t);
}
return t;
}
//右旋转平衡: 调整结点的右孩子( 还有其他版本的右孩子处理:即RL,RR)
AVL RightBalance(AVL t)
{
AVL p=t->Right;
switch(p->bf)
{
case RH: //插入的新节点在右子树的右子树上 ,进行单左旋处理
t->bf=t->bf=EH;
t=LeftRot(t);
case LH: //插入的新节点在右孩子的左子树上
AVL l=p->Left;
switch(l->bf)
{
case RH:
t->bf=LH;
p->bf=EH;
break;
case EH:
t->bf=EH;
p->bf=EH;
break;
case LH:
t->bf=EH;
p->bf=RH;
break;
}
t->Right=RightRot(t->Right);
t=LeftRot(t);
}
return t;
}
//插入数据(考虑插入相同的数)
bool Insert(AVL t,int x,bool stute)
{
if(t==NULL)
{
AVL t= new Node;
t->Left=t->Right=NULL;
t->data=x;
t->bf=EH;
stute=true;
}
else if(x<t->data)
{
if(!Insert(t->Left,x,stute))
return false;
if(stute)
{
switch(t->bf)
{
case LH:
t=LeftBalance(t);
stute=false;
break;
case EH:
t->bf=LH;
stute=true;
break;
case RH:
t->bf=EH;
stute=false;
break;
}
}
}
else if(x==t->data)
{
stute=false;
return false;
}
else
{
if(!Insert(t->Right,x,stute)) return false;
if(stute)
{
switch(t->bf)
{
case LH:
t->bf=EH;
stute=false;
break;
case EH:
t->bf=RH;
stute=true;
break;
case RH:
t=RightBalance(t);
stute=false;
break;
}
}
}
return true;
}
代码2、
#include<bits/stdc++.h>
using namespace std;
typedef struct Node{
int data;
struct Node* Left;
struct Node* Right;
int height;
}*AVLTree;
int Max(int a,int b)
{
return a>b?a:b;
}
//插入
AVLTree Insert(AVLTree T,int X)
{
if(!T)
{
T=(AVLTree)malloc(sizeof(struct Node));
T->data=X;
T->Left=T->Right=NULL;
}
else if(X<T->data)
{
T->Left=Insert(T->Left,X);
if(GetHeight(T->Left)-GetHeight(T->Right)==2)
{
if(X<T->Left->data) T=SingleLetfRotation(T);
else T=DoubleLeftRotation(T);
}
}
else if(X>T->data)
{
T->Right=Insert(T->Right,X);
if(GetHeight(T->Left)-GetHeight(T->Right)==-2)
{
if(X>T->Right->data) T=SingleRightRotation(T);
else T=DoubleRightRotation(T);
}
}
T->height=Max(GetHeight(T->Left),GetHeight(T->Right))+1;
return T;
}
//单右旋
AVLTree SingleLeftRotation(AVLTree A)
{
AVLTree B=A->Left;
A->Left=B->Right;
B->Right=A;
A->height=Max(GetHeight(A->Left),GetHeight(A->Right))+1;
B->height=Max(GetHeight(B->Left),A->height)+1;
return B;
}
//左右双旋
AVLTree DoubleRightRotation(AVLTree A)
{
A->Left=SingleRightRotation(A->Left);
return SingleLeftRotation(A);
}