您的位置:首页 > 理论基础 > 数据结构算法

C++代码,数据结构-平衡二叉树

2014-02-19 23:56 260 查看
***L的插入建立算法,用到了递归,且要分好几种一般情况来解决各类情况。

总体分为四种情况,

LL型,LR型,RR型,RL型;

下面说一下LL 型,和LR型的情况,另外两种的情况与这两种为镜像关系;

LL型,LR型,设结点A,A是离插入点最近,且平衡因子为1,(结点平衡因子左子树深度减去右子树深度)

LL型:

在A的左子树根节点的左子树上插入结点F,导致A结点的平衡因子又1变到了2, 所以对A结点要进行右旋操作

代码中的
R_rotate(a)
具体实现过程如图



------------A结点右旋-------------------->



F点为插入点,

注意:在代码中还有修改相关点的平衡因子

LR型:

在A的左子树根节点的右子树上插入结点F,导致A结点的平衡因子又1变到了2,所以对、要进行两次操作,先左旋,再右旋

代码中的:

L_rotata(A->lchild);
    R_rotate(A);


LR再细分有两种情况

插入点为左孩子还是右孩子

代码中的体现是

Bstree rd=lc->rchild;
    switch(rd->bf){
case LH:T->bf=RH; lc->bf=EH;break;
case EH:T->bf=lc->bf=EH;break;
case RH:T->bf=EH;lc->bf=LH;break;
    }
关系到相关结点平衡因子的修改。如有疑惑可以看下面的图

1.插入点为左孩子


--先对B结点进行左旋-,--->

----对A右旋----->



变成了LL的情况,在对A进行右旋即可

但是不要忘了修改相关结点的平衡因子。

2.插入点为右孩子


--先对B结点进行左旋-,--->

--对A右旋----->


变成了LL的情况,在对A进行右旋即可

但是不要忘了修改相关结点的平衡因子。

下面是完整代码,没有写删除代码,和查询代码,

#include<iostream>
#include<fstream>
#include<cstdlib>
#include<queue>
using namespace std;

//平衡二叉树的建立,遍历,,

struct Bstnode{
int data;
int bf;//平衡因子
Bstnode*lchild,*rchild;
};
typedef Bstnode * Bstree;

#define LH +1
#define EH 0
#define RH -1

void R_rotate(Bstree &p){//右旋,
Bstree lc=p->lchild;
p->lchild=lc->rchild;
lc->rchild=p;
p=lc;
}
void L_rotata(Bstree &p){//左旋,
Bstree rc=p->rchild;
p->rchild=rc->lchild;
rc->lchild=p;
p=rc;

}

void Leftbalance(Bstree &T){//左子树的平衡处理
Bstree lc=T->lchild;
switch(lc->bf){//LL的情况
case LH:
T->bf=lc->bf=EH;
R_rotate(T);break;

case RH://LR的情况,同时针对rd上的不同情况,进行对T,lc的平衡因子的设置
Bstree rd=lc->rchild; switch(rd->bf){ case LH:T->bf=RH; lc->bf=EH;break; case EH:T->bf=lc->bf=EH;break; case RH:T->bf=EH;lc->bf=LH;break; }
rd->bf=EH;
L_rotata(T->lchild);
R_rotate(T);
}

}

void Rightbalance(Bstree &T)//右子树的平衡处理,与左子树的平衡处理类似
{
Bstree rc=T->rchild;
switch (rc->bf){
case RH:
T->bf=rc->bf=EH;
L_rotata(T);break;
case LH:
Bstree ld=rc->lchild;
switch(ld->bf){
case LH:
T->bf=EH; rc->bf=RH;break;
case EH:
T->bf=rc->bf=EH;break;
case RH:
T->bf=LH; rc->bf=EH;break;

}
ld->bf=EH;
R_rotate(T->rchild);
L_rotata(T);
}

}

bool Insert***L(Bstree &T,int e,bool &taller){
if(!T){//此结点为空,则插入,并设置该点平衡因子为0,taller为true,长高了
T=new Bstnode;
T->data =e; T->lchild=T->rchild=NULL; T->bf=EH; taller=true;
}
else
{
if(e==T->data){taller =false; return 0;}//已经存在,不插入,返回0;
if(e<T->data){//如果e小于本结点,则继续在左子树搜索,
if(!Insert***L(T->lchild,e,taller))return 0;//未插入,返回0;
if(taller)//已经插入到了左子树,则要检查平衡度,
{ //注意!检查平衡度是由下往上的,哪个结点的失去平衡,则对该结点进行平衡操作
switch(T->bf){
case LH: //本结点本来左比右高,现在插入了,所以要做平衡处理
Leftbalance(T);taller=false; break;
case EH: //本来等高,现在插入了,所以本结点平衡因子为1;taller 设为false ,进入下一个递归的时候,不需要在检查平衡;
T->bf=LH; taller=true;break;
case RH://本来右边高,现在插入了,所以本结点平衡因子为0;taller 设为false ,进入下一个递归的时候,不需要在检查平衡;
T->bf =EH; taller=false; break;
}

}

}
else{//在右子树中查找
if(!Insert***L(T->rchild,e,taller))return 0;//未插入,返回0;
if(taller){ //同上,检查平衡
switch(T->bf){
case LH://本来左高,现在等高
T->bf=EH; taller=false; break;
case EH://本来平衡,现在右增高了,所以本结点平衡因子为-1.taller为true,进入下一个递归是继续检查平衡,
T->bf=RH;taller=true;break;
case RH://本来右高,现在右又增高了,所以失去平衡,对该节点进行平衡处理
Rightbalance(T);taller=false;break;
}
}
}

}

return 1;
}

void visit(int c){
cout<<c<<" ";}

void cengcitravel(Bstree T){
Bstree p;
queue<Bstree>sq;
sq.push(T);
while(!sq.empty()){
p=sq.front();
visit(p->data);
if(p->lchild)sq.push(p->lchild);
if(p->rchild)sq.push(p->rchild);
sq.pop();
}

}

int main(){

int x;
Bstree T=NULL;
bool f=false;
while(cin>>x){
Insert***L(T,x,f);
}
cin.clear();
cengcitravel(T);//输出序列
cout<<endl;

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