折腾了一天,总算弄明白了点AVL树。其实概念上还是挺好理解的,无非是左旋右旋,但是个人认为最难理解的就是旋转后如何处理结点的bf值,即旋转后是左高还是右高还是平衡。各个教材中讲的都不详细,太难理解了,后来上网找到了一篇http://www.cnblogs.com/longdouhzt/archive/2011/07/20/2112089.html,确实读了很有帮助,觉得教材中写的弱爆了。。。。。。不过可以看出来,这篇文章中写的方法,局限在于修改了树的结点类型,添加了指向父节点的指针。而大多数教程中结点类型都没有父节点指针,想要完成修改父节点指针bf值,采用了递归和一个taller变量。我把这两种思想结合了一下,用普通的树结点类型实现AVL树,完成了下边的代码:
代码思路是:
插入一个节点,从根节点开始判断,一级一级递归,找到合适的位置插入,插入后自底向上,如若需要平衡就平衡,并修改节点bf值和taller值,最后递归到根节点完成此次插入。
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
const int LH=1; //左子树比右子树高1
const int EH=0; //左右子树一样高
const int RH=-1;//右子树比左子树高1
const int MAX_NODE_NUM=20; //结点数目上限
struct AvlNode
{
int data;
int bf;
AvlNode *lchild;
AvlNode *rchild;
};
class AvlTree
{
public:
int Get_data(AvlNode *p)
{
return p->data;
}
bool Insert_Avl(AvlNode **T,int num,bool &taller);
void L_Rotate(AvlNode **T);
void R_Rotate(AvlNode **T);
void Left_Balance(AvlNode **T);
void Right_Balance(AvlNode **T);
void InOrder_Traverse(AvlNode *T);
void Level_Traverse(AvlNode *T);
void PreOrder(AvlNode * Node);
};
void AvlTree::L_Rotate(AvlNode **T)
{
AvlNode *P=(*T)->rchild;
(*T)->rchild=P->lchild;
P->lchild=*T;
if(P->bf<0)
(*T)->bf=(*T)->bf+1-P->bf;
else
(*T)->bf=(*T)->bf+1;
if((*T)->bf>0)
P->bf=P->bf+1+(*T)->bf;
else
P->bf=P->bf+1;
*T=P;
}
void AvlTree::R_Rotate(AvlNode **T)
{
AvlNode *P=(*T)->lchild;
(*T)->lchild=P->rchild;
P->rchild=*T;
if(P->bf>0)
(*T)->bf=(*T)->bf-1-P->bf;
else
(*T)->bf=(*T)->bf-1;
if((*T)->bf<0)
P->bf=P->bf-1-(*T)->bf;
else
P->bf=P->bf-1;
*T=P;
}
void AvlTree::Left_Balance(AvlNode **T)
{
if ((*T)->rchild->bf == 1)
R_Rotate(&(*T)->rchild);
L_Rotate(T);
}
void AvlTree::Right_Balance(AvlNode **T)
{
if ((*T)->lchild->bf == -1)
L_Rotate(&(*T)->lchild);
R_Rotate(T);
}
void AvlTree::InOrder_Traverse(AvlNode *T) //中序遍历
{
stack<AvlNode *> s;
AvlNode *p=T;
while(p || !s.empty())
{
if(p)
{
s.push(p);
p=p->lchild;
}
else
{
p=s.top();
s.pop();
cout<<p->data<<” “;
p=p->rchild;
}
}
}
void AvlTree::Level_Traverse(AvlNode *T) //层次遍历
{
queue<AvlNode *> q;
AvlNode *p=T;
q.push(p);
while(!q.empty())
{
p=q.front();
q.pop();
cout<<p->data<<“: “<<p->bf<<endl;
if(p->lchild)
q.push(p->lchild);
if(p->rchild)
q.push(p->rchild);
}
}
void AvlTree::PreOrder(AvlNode * Node)//前序遍历
{
if(Node != NULL)
{
printf(“%d “, Node->data);
PreOrder(Node->lchild);
PreOrder(Node->rchild);
}
}
bool AvlTree::Insert_Avl(AvlNode **T,int data,bool &taller)
{
if(!*T)
{
*T=new AvlNode;
(*T)->data=data;
(*T)->lchild=NULL;
(*T)->rchild=NULL;
(*T)->bf=EH;
taller=true;
}
else
{
if(data==(*T)->data)
{
taller=false;
return false;
}
if(data<(*T)->data)
{
if(!Insert_Avl(&(*T)->lchild,data,taller))
return false;
if(taller)
switch((*T)->bf)
{
case LH:
cout<<“rightbalanc: “<<(*T)->data<<endl;
(*T)->bf=2;
Right_Balance(T);
taller=false;
break;
case EH:
(*T)->bf=LH;
taller=true;
break;
case RH:
(*T)->bf=EH;
taller=false;
break;
}
}
else
{
if(!Insert_Avl(&(*T)->rchild,data,taller))
return false;
if(taller)
switch((*T)->bf)
{
case LH:
(*T)->bf=EH;
taller=false;
break;
case EH:
(*T)->bf=RH;
taller=true;
break;
case RH:
cout<<“leftbalanc: “<<(*T)->data<<endl;
(*T)->bf=-2;
Left_Balance(T);
taller=false;
break;
}
}
}
return true;
}
int main()
{
int i;
int a[10]={3,2,1,4,5,6,7,10,9,8};
int b[6]={3,2,1,4,5,6};
AvlTree T;
AvlNode *root=NULL;
bool taller;
for(i=0;i<10;i++)
{
T.Insert_Avl(&root,a[i],taller);
}
T.InOrder_Traverse(root);
cout<<“root: “<<root->data<<endl;
T.PreOrder(root);
T.Level_Traverse(root);
system(“pause”);
return 0;
}