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

来源:互联网 发布:手机指纹锁软件 编辑:程序博客网 时间:2024/06/07 09:30

AVL的插入建立算法,用到了递归,且要分好几种一般情况来解决各类情况。

总体分为四种情况,

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 -1void 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 InsertAVL(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(!InsertAVL(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(!InsertAVL(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){   InsertAVL(T,x,f);}cin.clear();cengcitravel(T);//输出序列cout<<endl;return 0;}



0 0
原创粉丝点击