课题B6:平衡二叉树的构造及输出
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*
Author: corpio
E-mail: wangzh@, wvh2007@
QQ: 1027690187
Address:上海市浦东新区橄榄路1350号 上海电机学院 电子信息学院
If you have any problems or find some bugs, please contact with the author!
Thank you!
*/
#include
#define ENDNUM -32768
typedef struct _node
{
int key;
struct _node *lchild;
struct _node *rchild;
struct _node *parent;
} Node;
// 求二叉树的高度
int TreeTall(Node *T)
{
int L_Len, R_Len;
if(T==NULL)
return 0;
else
{
L_Len=TreeTall(T->lchild);
R_Len=TreeTall(T->rchild);
return (L_Len>R_Len)?(L_Len+1):(R_Len+1);
}
}
// 递归判断二叉树是否平衡,bf为平衡因子
int IsBlance(Node *T)
{
int bf;
if(T!=NULL)
{
bf=TreeTall(T->lchild)-TreeTall(T->rchild);
if( (bf<-1)||(bf>1) )
return 0;
else
{
if(IsBlance(T->lchild) && IsBlance(T->rchild))
return 1;
else
return 0;
}
}
else
return 1;
}
// 单向右旋转,T指向树根,a指向离插入点最近的不平衡祖先结点
Node *R_rotate(Node *T, Node *a)
{
Node *b, *p, *c, *d;
p=a->parent;
b=a->lchild;
c=b->lchild;
d=b->rchild;
a->lchild=d;
if(d!=NULL)
d->parent=a;
b->rchild=a;
a->parent=b;
if(p==NULL)
{
T=b;
b->parent=NULL; //b的父结点为空,即b就是根结点
}
else if(p->lchild==a) //如果a是父结点的左孩子
{
p->lchild=b; //将b赋值给p的左孩子
b->parent=p; //b的父结点是p
}
else if(p->rchild==a) //如果a是父结点的右孩子
{
p->rchild=b; //将b赋值给p的右孩子
b->parent=p; //b的父结点是p
}
return T;
}
//单向左旋转,T指向树根,a指向离插入点最近的不平衡祖先结点
Node *L_rotate(Node *T, Node *a)
{
Node *b, *p, *c, *d;
p=a->parent;
b=a->rchild;
c=b->rchild;
d=b->lchild;
a->rchild=d;
if(d!=NULL)
d->parent=a;
b->lchild=a;
a->parent=b;
if(p==NULL)
{
T=b; //二叉树的根结点就是b,把b赋值给树T
b->parent=NULL; //b的父结点为空,即b就是根结点
}
else if(p->lchild==a) //如果a是父结点的左孩子
{
p->lchild=b; //将b赋值给p的左孩子
b->parent=p; //b的父结点是p
}
else if(p->rchild==a) //如果a是父结点的右孩子
{
p->rchild=b; //将b赋值给p的右孩子
b->parent=p; //b的父结点是p
}
return T;
}
//先左旋转后右旋转,T指向树根,a指向离插入点最近的不平衡祖先结点
Node *LR_rotate(Node *T,Node *a)
{
Node *b,*c,*p,*d,*e;
p=a->parent;
b=a->lchild; //a的左孩子为b
c=b->rchild; //b的左孩子为c
d=c->lchild; //c的左孩子为d
e=c->rchild; //c的右孩子为e
//左旋 第一条链
b->rchild=c->lchild; //将c的左孩子赋值给b的左孩子
if(d!=NUL
L) //如果d不为空,即d是存在的时候
d->parent=b; //d的父结点为b
//左旋 第二条链
a->lchild=c; //把c赋值给a的左孩子
c->parent=a; //a是c的父结点
//左旋 第三条链
c->lchild=b; //把b赋值给c的左孩子
b->parent=c; //b的父结点是c
//右旋 第一条链
a->lchild=c->rchild; //把c的右孩子赋值给a的左孩子
if(e!=NULL)
e->parent=a; //e的父结点为a
//右旋 第二条链
c->rchild=a; //把a赋值给c的右孩子
a->parent=c; //a的父结点为c
if(p==NULL) //如果a的父结点为空,即a就是根结点的时候
{
T=c; //二叉树的根结点就是c,把c赋值给树T
c->parent=NULL; //c的父结点为空,即c就是根结点
}
else if(p->lchild==a) //如果a为父结点的左孩子
{
p->lchild=c; //c为父结点的左孩子
c->parent=p; //c的父结点为p
}
else if(p->rchild==a) //如果a为父结点的右孩子
{
p->rchild=c; //c为父结点的右孩子
c->parent=p; //c的父结点为p
}
return T;
}
//先右旋转后左旋转,T指向树根,a指向离插入点最近的不平衡祖先结点
Node *RL_rotate(Node *T,Node *a)
{
Node *b,*c,*p,*d,*e;
p=a->parent;
b=a->rchild; //a的左孩子为b
c=b->lchild; //b的左孩子为c
d=c->rchild; //c的右孩子为d
e=c->lchild; //c的左孩子为e
//右旋 第一条链
b->lchild=c->rchild; //把c的右孩子赋值给b的左孩子
if(d!=NULL) //当d不为空时
d->parent=b; //d的父结点为b
//右旋 第二条链
a->rchild=c; //把c赋值给a的右孩子
c->parent=a; //c的父结点为a
//右旋 第三条链
c->rchild=b; //把b赋值给c的右孩子
b->parent=c; //b的父结点为c
//左旋 第一条链
a->rchild=c->lchild; //把c的左孩子赋值给a的右孩子
if(e!=NULL)
e->parent=a; //e的父结点为a
//左旋 第二条链
c->lchild=a; //把a赋值给c的左孩子
a->parent=c; //a的父结点为c
if(p==NULL) //如果a的父结点为空,即a就是根结点的时候
{
T=c; //二叉树的根结点就是c,把c赋值给树T
c->parent=NULL; //c的父结点为空,即c就是根结点
}
else if(p->lchild==a) //如果a为父结点的左孩子
{
p->lchild=c; //c为父结点的左孩子
c->parent=p; //c的父结点为p
}
else if(p->rchild==a) //如果a为父结点的右孩子
{
p->rchild=c; //c为父结点的右孩子
c->parent=p; //c的父结点为p
}
return T;
}
void InOrder(Node *T)
{
if(T!=NULL)
{
InOrder(T->lchild);
printf("%4d", T->key);
InOrder(T->rchild);
}
}
void PreOrder(Node *T)
{
if(T!=NULL)
{
printf("%4d", T->key);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
Node *InsertNode(Node *T,int data)
{
Node *p, *q, *s, *r; //p用来开辟新结点;q用来查找插入点;s用来保留插入点;
Node *a;
int bf; //
kind为旋转类型,bf为节点的平衡因子
p=new Node; //开辟内存空间
p->key=data; //构造节点
p->lchild=NULL;
p->rchild=NULL;
p->parent=NULL;
if(T==NULL)
T=p;
else
{
s=q=T; //s,q指向根结点
while(q!=NULL) //当q指向非空时执行下面的循环语句,当q指向为空退出循环
{
if( data
{
s=q;
q=q->lchild;
}
else if( data>q->key ) //当待插入的数据大于当前的根节点时,指向根结点的指针下移(指向右孩子);s则指向最后一个叶节点
{
s=q;
q=q->rchild;
}
else
break;
}
//以下为插入节点的代码
if( data>s->key ) //若待插入的结点数据大于相应的叶结点时
{
s->rchild=p; //最后的相应叶结点的右孩子为p(待插入的数据)
p->parent=s; //刚插入结点的父指针指向s
}
else if( data
{
s->lchild=p; //最后的相应叶结点的右孩子为p(待插入的数据)
p->parent=s; //刚插入结点的父指针指向s
}
//判断类型并旋转
if(IsBlance(T)==0) //如果二叉树是不平衡的
{
r=s;
bf=TreeTall(r->lchild)-TreeTall(r->rchild);
while( (bf>=-1)&&(bf<=1) )
{
r=r->parent;
bf=TreeTall(r->lchild)-TreeTall(r->rchild);
}
a=r;
if( p->key>a->key && p->key>a->rchild->key)
{ //kind=2;
printf("输入%d时,导致不平衡,需要进行单向左旋平衡处理!\n", p->key);
T=L_rotate(T,a);
printf("调整后,该平衡二叉树的先序序列为:");
PreOrder(T);
printf("\n中序序列为:");
InOrder(T);
}
else if(p->key>a->key && p->key
{ //kind=4;
printf("输入%d时,导致不平衡,需要进行先右旋后左旋平衡处理!\n", p->key);
T=RL_rotate(T,a);
printf("调整后,该平衡二叉树的先序序列为:");
PreOrder(T);
printf("\n中序序列为:");
InOrder(T);
}
else if(p->key
{ //kind=3;
printf("输入%d时,导致不平衡,需要进行先左旋后右旋平衡处理!\n", p->key);
T=LR_rotate(T,a);
printf("调整后,该平衡二叉树的先序序列为:");
PreOrder(T);
printf("\n中序序列为:");
InOrder(T);
}
else
{ //kind=1;
printf("输入%d时,导致不平衡,需要进行单向右旋平衡处理!\n", p->key);
T=R_rotate(T,a);
printf("调整后,该平衡二叉树的先序序列为:");
PreOrder(T);
printf("\n中序序列为:");
InOrder(T);
}
printf("\n");
}//end if(IsBlance(T)==0)
}//end if(T==NULL)
return T;
}
void main()
{
int tmp, i=0;
Node *T;
printf("请输入一些整数构成二叉排序树,当输入-32768时,输入结束!\n");
printf("请输入第%d个整数:", ++i);
scanf("%d", &tmp);
T=NULL;
while(tmp!=ENDNUM)
{
T=InsertNode(T,tmp);
printf("\n请输入第%d个整数:", ++i);
scanf("%d", &tmp);
}
printf("该平衡二叉树的先序序列为:");
PreOrder(T);
printf("\n");
printf("该平衡二叉树的中序序列为:");
InOrder(T);
printf("\n树高:%d\n", TreeTall(T));
if(IsBlance(T)==1)
{
printf("二叉树是平衡的,其中序遍历结果为:");
InOrder(T);
printf("\n");
}
}