您的位置:首页 > 其它

平衡二叉排序树

2015-06-21 21:49 447 查看
因为二叉树本身就是个递归的概念,所以在构建平衡二叉树的时候,应时刻记得递归这个概念。

同样的序列,因为排序不同,可能会生成不同的二叉排序树,查找效率性对就不一定了,如:1-9这些数字就可以生成下面两种树。





第二种就是一个极端的情况,如果要查找9,就需要进行比较8次,效率很低。由此就引出,平衡二叉树的概念。

什么是平衡二叉树?





希望对一个序列,进行查找,最好的就是将其构建成一个平衡二叉树即AVL树。

但是怎么构建平衡二叉排序树?

前提:必须是一棵树。(类似于:只有先保证他是一个人,才难说他是一个什么样的男人。嘻嘻,这个比喻不是那么准确啦)

下面有一个题目:

怎么将左图构建成右图的平衡二叉树呢?





可见,左图和右图的不同就在于是否是平衡的。左图中节点9的平衡因子是2,是个不平衡点。

构造平衡二叉树:

如果在一棵平衡的二叉搜索树中,插入一个新节点时,造成了不平衡。此时必须调整树的结构,使之平衡化。

平衡旋转有两类:

--单旋转(左旋和右旋)

--双旋转(左右旋和右左旋)

每插入一个新节点时,AVL树中相关节点的平衡状态会发生改变。因此,在插入一个新节点后,需要从插入位置沿着通向根的路径回溯,检查各节点的平衡因子。如果在某一节点发现此树不平衡,停止回溯。

从发生不平衡的节点起,沿着刚才回溯的路径取直接下两层的节点。

(1)如果这三个节点处在一条直线上,则采用单旋转进行平衡化。单旋转可按方向分为左单旋转和右单旋转。

(2)如果这三个节点处在一条折线上,则采用双旋转进行平衡化。单旋转可按方向分为先左后右旋转和先右后左旋转。





下面举两个简单的例子,便于理解。

1:a[10]={3,2,1,4,5,6,7,10,9,8};对于这压样一个一维数组,构建二叉平衡树。















此时构建过程已经完成。

例子2:







下面是代码实现:

/*平衡二叉树的实现原理
时间:2015-6-21
***/
#define LH 1//左子树高
#define EH 1//左右子树登高
#define RH 1//右子树

typedef struct BITNode{
int data;
int bf;
struct BITNode*lchild,*rchild;
}BITNode,*BiTree;
//右旋操作
void R_Rotate(BiTree *p)
{
BiTree L;
L=(*p)->lchild;
(*p)->lchild=L->rchild;
L->rchild=(*p);
*p=L;
}
//左旋操作
void L_Rotate(BiTree *p)
{
BiTree L;
L=(*p)->rchild;
(*p)->rchild=L->lchild;
L->lchild=(*p);
*p=L;
}
//左平衡
void LeftBalance(BiTree *T)
{
BiTree L,lr;
L=(*T)->lchild;
switch(L-bf)
{
case LH;
(*T)->bf=L-bf=EH;
R_RETATE(T)
break;
case RH;
lr=L->rchild;
switch(Lr-bf)
{
case LH;
(*T)->bf=RH;
L->bf=EH;
break;
case EH;
(*T)->bf=L-bf=EH;
break;
case RH;
(*T)->bf=EH;
L-bf=LH;
break;
}
lR->bf=EH;
L_Rotate(&(*T)->lchild);
R_Rotate(T);
}

}
int InsertAVL(BITree *T,int n,int *taller)//taller用于判断插入节点后,树长高了没有
{
if(!*T)
{
*T=(BiTree)malloc(sizeod(BITNode));
(*T)->data=e;
(*T)->lchild=(*T)->rchild=NULL;
(*T)->bf=EH;
*taller=TRUE;
}
else{
if(e==(*T)->data)
{
*taller=FALSE;
return FALSE;
}
if(e<(*T)->data)
{
if(!InsertAVL(&(*T))->lchild,e,taller)
{
return FALSE;
}
if(*taller)//判断树的长势
{
switch((*T)->bf)
{
case LH:
LeftBalance(T);
*taller=FALSE;
break;
case EH:
(*T)->bf=EH;
*taller=TRUE;
break;
case RH:
(*T)->bf=EH;
*taller=FALSE;

}
}

}
else
{
if(!InsertAVL(&(*T))->rchild,e,taller)
{
return FALSE;
}
if(*taller)//判断树的长势
{
switch((*T)->bf)
{
case LH:
(*T)->bf=EH;
*taller=FALSE;
break;
case EH:
(*T)->bf=EH;
*taller=TRUE;
break;
case RH:
RightBalance(T);
(*T)->bf=EH;
*taller=FALSE;

}
}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: