接上篇,这次是内个AV树的作业,各种旋转容易让人头晕,参考严蔚敏教材完成:
struct node
{
int data;
int bf;//平衡因子
node *left;
node *right;
};
bool find(node* root,int key)//查找key是否在树中已经出现过
{
if(NULL==root)
return false;
if(key==root->data)
return true;
if(key < root->data)
return find(root->left,key);
if(key > root->data)
return find(root->right,key);
return false;
}
inline void R_Rotate(node* &root)//将以root为根的树右旋处理,处理后root指向新节点——处理前左子树的根节点
{
node* Lch=root->left;//Lch指向根节点的左子树根节点
root->left=Lch->right;//根节点的左子树转向
Lch->right=root;//左子树的右孩子指向根节点
root=Lch;//更新根节点
}
inline void L_Rotate(node* &root)//将以root为根的树左旋处理,处理后root指向新节点——处理前右子树的根节点
{
node* Rch=root->right;//Rch指向根节点的右子树节点
root->right=Rch->left;//根节点的右子树转向
Rch->left=root;
root=Rch;
}
void R_balance(node* &root)//右平衡处理
{
node* Rch=root->right;
switch (Rch->bf)
{
case -1://右孩子的右子树深
root->bf=Rch->bf=0;
L_Rotate(root);
break;
case 1://右孩子的左子树深
node* R_Lch=Rch->left;//新节点插入在root的右孩子的左子树上,并进行双旋处理
switch (R_Lch->bf)//修改根节点及其右孩子的平衡因子
{
case 1:
root->bf=0;
Rch->bf=-1;
break;
case 0:
root->bf=Rch->bf=0;
break;
case -1:
root->bf=1;
Rch->bf=0;
break;
}
R_Lch->bf=0;
R_Rotate(root->right);//先右旋右孩子
L_Rotate(root);//再左旋根节点
break;
}
}
void L_balance(node* &root)//左平衡处理
{
node* Lch=root->left;
switch (Lch->bf)
{
case 1://左孩子的左子树深
root->bf=Lch->bf=0;//新节点插入在root左孩子的左子树上,并做单右旋处理
R_Rotate(root);
break;
case -1://左孩子的右子树深
node* L_Rch=Lch->right;//新节点插入在root的左孩子的右子树上,并进行双旋处理
switch (L_Rch->bf)//修改根节点及其左孩子的平衡因子
{
case 1:
root->bf=-1;
Lch->bf=0;
break;
case 0:
root->bf=Lch->bf=0;
break;
case -1:
root->bf=0;
Lch->bf=1;
break;
}
L_Rch->bf=0;
L_Rotate(root->left);//先左旋左孩子
R_Rotate(root);//再右旋根节点
break;
}
}
bool insert_AVL(node* &root,int key,bool &taller)//插入成功返回true,否则false
{
if( NULL==root )
{
root=new node();
root->data=key;
root->left=root->right=NULL;
root->bf=0;//平衡度为0
taller=true;
return true;
}
if( find(root,key) )//key已在树中
{
taller=false;
return false;
}
if(key < root->data)//插入左子树
{
if( !insert_AVL(root->left,key,taller) )//插入失败
return false;
if(taller)//若树长高了
{
switch (root->bf)//看插入前平衡因子向哪边倾斜
{
case 1://左倾斜,插入后左边需调整
L_balance(root);
taller=false;//高度恢复
break;
case 0://平衡,不需调整
root->bf=1;//插入后更新平衡因子
taller=true;//并且树长高
break;
case -1://原来右子树高,插入后平衡
root->bf=0;//更新平衡因子
taller=false;
break;
}//switch
}//if
}//if
else//插入右子树
{
if( !insert_AVL(root->right,key,taller))
return false;
if(taller)
{
switch (root->bf)//看插入前平衡因子向哪边倾斜
{
case 1://左倾斜,插入平衡
root->bf=0;//更新平衡因子
taller=false;//高度恢复
break;
case 0://平衡,不需调整
root->bf=-1;//插入后更新平衡因子
taller=true;//并且树长高
break;
case -1://原来右子树高,插入后需右旋
R_balance(root);
taller=false;
break;
}//switch
}//if
}//if
return true;//插入成功
}
void lbr(node *root)//中序遍历
{
stack < node* > st;
while(NULL!=root || !st.empty() )
{
if(NULL!=root)
{
st.push(root);
root=root->left;
}
else
{
root=st.top();
st.pop();
printf("%d ",root->data);
root=root->right;
}
}
}
int main()
{
bool taller;
node* tree=NULL;
int key;
while(scanf("%d",&key)!=EOF)
{
insert_AVL(tree,key,taller);
}
lbr(tree);
return 0;
}
pzjay辛勤劳作,转载注明。