一.什么是AVL树?
这个二叉树的每一个节点的左右子树高度之差的绝对值小于等于1.(好了 没了 就这么简单)
二.结构
首先他是一个二叉树,二叉树该有的他都应该有,其次,他有一个东西,叫做平衡因子.
什么是平衡因子,我的理解是他的左子树高度减去右子树的高度的值,就是平衡因子.
好了,AVL的介绍就这么多.本文完.
--------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
怎么可能,都还没正式开始讲呢,我们拿出纸和笔,写一个普通的二叉树
比如说这个1,2,3吧,我们把3插入后有没发现问题,我们把3插入以后,他就不符合平衡二叉树的定义了啊(要问不符合什么定义的快仔细去看前面的红字)
那怎么办,Adelson-Velskii和Landis就想了这一个办法,旋转
怎么旋转?
我们把1掰下来,2放上去,然后,他又符合平衡二叉树的定义了,
那么,他为什么这样转啊,他怎么知道这样就可以保持平衡的啊.
其实,在插入一个节点的时候,只有四种情况,会出现不平衡的状态,
看清楚了啊,只有四种情况,这意味着什么,意味着可以直接套用啊
让我列出这四种情况,
第一种:LL型
第二种:RR型
第三种:LR型
第四种:RL型
好了,这就是四种状态,那么为什么叫什么LL,RL,LR之类的呢
我们来看RR型先
这里,我们插入1的时候发现不平衡了,然后把3顺时针旋转了一下,就变平衡了
再看LL型
我们把1逆时针旋转一下,他又平衡了,
好了,聪明的你一定知道什么是LR型了
我们把23逆时针旋转,旋转成1-2-3的样子,再把1顺时针旋转下来,他就又平衡了
思路来说很简单,
难的地方个人觉得是代码会难点
他涉及很多方面知识,(其实是我没测试几组数据,写法也很鱼,不保证对,大家如果测试出错务必评论告诉我)
代码如下
(特别提示一点,如果检测有一个节点的平衡因子变成2或者-2我们才进行旋转,比如一个节点为2,左子树平衡因子为1就LL,为-1就LR旋转,RR和RL类似)
(本咸鱼还没有把删除节点的做出来)
#include <iostream>
using namespace std;
struct avl
{
int data;
avl *l;
avl *r;
int h;//高度
int eq;//平衡因子
};
int stop;//停止回溯时候加eq(BF值)的标记
avl* LL(avl *tree)
{
avl *t=tree->l;
t->eq=0;
tree->eq=0;
t->l->eq=1;
tree->l=t->r;
t->r=tree;
return t;
}
avl* RR(avl *tree)
{
avl *t=tree->r;
tree->eq=0;
t->eq=0;
t->r->eq=-1;
tree->r=t->l;
t->l=tree;
return t;
}
avl* LR(avl *tree)
{
avl *t1=tree;
avl *t2=tree->l;
avl *t3=tree->l->r;
t3->eq=0;
t2->eq=1;
t1->eq=0;
//t1->l->eq=-1;
t1->l=t3->r;
t2->r=t3->l;
t3->l=t2;
t3->r=t1;
return t3;
}
avl* RL(avl *tree)
{
avl *t1=tree;
avl *t2=tree->r;
avl *t3=tree->r->l;
t3->eq=0;
t2->eq=0;
t1->eq=1;
t1->r=t3->l;
t2->l=t3->r;
t3->l=t1;
t3->r=t2;
return t3;
}
void addtree(avl **tree,int key)
{
if (*tree==NULL)
{
(*tree) = (avl*)malloc(sizeof(avl));
(*tree)->data=key;
(*tree)->eq=0;
(*tree)->l=NULL;
(*tree)->r=NULL;
(*tree)->h=0;
}
else
{
if (key==(*tree)->data)
{
cout<<"不允许输入已有项"<<endl;
return ;
}
else
{
if (key<(*tree)->data)
{
addtree(&(*tree)->l,key);//递归插入
if (stop!=0)
{
(*tree)->eq+=1;
if((*tree)->eq==0)
stop=0;//如果修改到某个数的BF值为0就把标记改为0
}
if ((*tree)->l==NULL||(*tree)->r==NULL)
{
//左边或者右边没有节点就不用动
}
else if ((*tree)->eq==2)//等于二或者等于负二说明这里就不平衡了
{
if ((*tree)->l->eq==1)
{
//LL
(*tree)=LL(*tree);
//
stop=0;
}
if ((*tree)->l->eq==-1)
{
//LR
(*tree)=LR(*tree);
//
stop=0;
}
}
else if((*tree)->eq==-2)
{
if ((*tree)->r->eq==1)
{
//RL
(*tree)=RL(*tree);
//
stop=0;
}
if ((*tree)->r->eq==-1)
{
//RR
(*tree)=RR(*tree);
//
stop=0;
}
}
}
else
{
addtree(&(*tree)->r,key);
if (stop!=0)
{
(*tree)->eq-=1;
if((*tree)->eq==0)
stop=0;//如果修改到某个数的BF值为0就把标记改为0
}
if ((*tree)->l==NULL||(*tree)->r==NULL)
{
//左边或者右边没有节点就不用动
}
else if((*tree)->eq==2)//等于二或者等于负二说明这里就不平衡了
{
if ((*tree)->l->eq==1)
{
//LL
(*tree)=LL(*tree);
//
stop=0;
}
if ((*tree)->l->eq==-1)
{
//LR
(*tree)=LR(*tree);
//
stop=0;
}
}
if((*tree)->eq==-2)//等于二或者等于负二说明这里就不平衡了
{
if((*tree)->r->eq==1)
{
//RL
(*tree)=RL(*tree);
//
stop=0;
}
if((*tree)->r->eq==-1)
{
//RR
(*tree)=RR(*tree);
//
stop=0;
}
}
}
}
}
if ((*tree)->l==NULL||(*tree)->r==NULL)
{
if ((*tree)->l!=NULL||(*tree)->r!=NULL)
{
(*tree)->h+=1;
}
return;
}
(*tree)->h=((*tree)->l->h>=(*tree)->r->h)?((*tree)->l->h+1):((*tree)->r->h+1);//记得调整高度
}
int main()
{
stop=1;
avl *tree=NULL;
addtree(&tree,5);
stop=1;
addtree(&tree,4);
stop=1;
addtree(&tree,6);
stop=1;
addtree(&tree,7);
stop=1;
addtree(&tree,1);
stop=1;
addtree(&tree,9);
stop=1;
addtree(&tree,3);
stop=1;
addtree(&tree,8);
stop=1;
addtree(&tree,10);
stop=1;
addtree(&tree,2);
return 0;
}