#include <stdio.h>
#include<stdlib.h>
#define Ok 1
#define Error 0
#define max 20
#define Status int
#define LH 1
#define EH 0
#define RH -1
typedef struct Btree{
Btree *lchild;
Btree *rchild;
int data;
int bf;//用来记录该节点所处的状态0,1或-1
}Btree,*Bitree;//平衡二叉树节点的结构体
/*Btree *creattree(Bitree &b)//用来创建二叉树的,但是算法中有从根节点创建的语句,所以这一步就省略了
{
int ch1;
scanf("%d",&ch1);
if(ch1==0)
b=NULL;
else
{
b=(Btree*)malloc(sizeof(Btree));
if(!b) exit(1);
b->data=ch1;
printf("请输入%d的左节点",b->data);
b->lchild=creattree(b->lchild);
printf("请输入%d的右节点",b->data);
b->rchild=creattree(b->rchild);
}
return b;
}*/
Status inital(Bitree &b)//初始化树
{
b=(Btree*)malloc(sizeof(Btree));//不先初始化给树一个地址的话,在主函数里b是传递不进去的,会报错
b=NULL;
return 1;
}
bool EQ(int i,int j)
{
if(i==j)
return 1;
else
return 0;
}
bool LT(int i,int j)
{
if(i<j)
return 1;
else
return 0;
}
void R_Rotate(Bitree &p)//单项右旋处理
{
Bitree lc;
lc=p->lchild; //需要将p与他的左孩子节点旋转
p->lchild=lc->rchild;//将左孩子的右节点给根节点做左孩子节点
lc->rchild=p;//让根节点做它以前左孩子结点的右孩子节点
p=lc;//转换根节点
}
void L_Rotate(Bitree &p)//单项左旋处理
{
Bitree lc;
lc=p->rchild; //道理同上
p->rchild=lc->lchild;
lc->lchild=p;
p=lc;
}
void leftBalance(Bitree &t)//当以t为根节点已经左子树比右子树多1个高度的情况下再向左子树叶子节点插入一个节点
{
Bitree lc,rd;
lc=t->lchild;
switch(lc->bf){//查看插入后t的左孩子的状态
case LH://如果插入后左子树比右子树高
t->bf=lc->bf=EH;//重置t和他左子树的状态
R_Rotate(t);//进行单向右旋处理
break;
case RH://如果插入后右子树比左子树高,须进行双旋处理
rd=lc->rchild;
switch(rd->bf)//这一步得根据分析的图来进行旋转后的赋值
{
case LH:
t->bf=RH; lc->bf=EH;
break;
case RH:
t->bf=EH; lc->bf=LH;
break;
case EH:
t->bf=lc->bf=EH;
break;
}
break;
rd->bf=EH;
L_Rotate(t->lchild);//先对t的左孩子节点做单向做平衡处理
R_Rotate(t);//再对t做单向右平衡处理
}
}
void RightBalance(Bitree &t)//当以t为根节点已经右子树比左子树多1个高度的情况下再向右子树叶子节点插入一个节点
{
Bitree rc,ld;
rc=t->rchild;
switch(rc->bf)
{
case RH:
rc->bf=t->bf=EH;
L_Rotate(t);
break; //同上
case LH:
ld=rc->lchild;
switch(ld->bf)
{
case RH: t->bf=LH; rc->bf=EH;
break;
case LH: t->bf=EH; rc->bf=RH;
break;
case EH: t->bf=rc->bf=EH;
break;
}
ld->bf=EH;
R_Rotate(t->rchild);
L_Rotate(t);
break;
}
}
Status InsertAVL(Bitree &t,int e,bool &taller)//插入平衡二叉树的节点函数
{
if(!t){ //插入节点成功
t=(Bitree)malloc(sizeof(Btree));
t->data=e; t->lchild=t->rchild=NULL;
t->bf=EH; taller=true;
}
else {
if(EQ(e,t->data)) //如果插入的节点在树中已经是存在的了,那么不用查了,
{taller=false; return 0;}
if(LT(e,t->data))//如果插入的节点是在左子树中
{
if(!InsertAVL(t->lchild,e,taller)) return 0;//一直递归到要插入的叶子节点的位置
if(taller)//如果成功插入一个叶子节点,需要看它是否符合平衡二叉树要求,再修改
{
switch(t->bf)
{
case LH://如果它的父节点在插入前就是左子树比右子树大的话
leftBalance(t); taller=false; //当以t为根节点已经左子树比右子树多1个高度的情况下再向左子树叶子节点插入一个节点
break;
case EH://如果它的父节点在插入前就是左子树与右子树高度相等时
t->bf=LH; taller=true; //记录父节点左子树比右子树高1
break;
case RH://如果它的父节点在插入前就是左子树比右子树小1的话
t->bf=EH; taller=false;//此时父节点左右子树相等
break;
}
}
}
else { //当插入的节点在右子树的话。。。。。道理同上
if(!InsertAVL(t->rchild,e,taller)) return 0;
if(taller)
{
switch(t->bf)
{
case LH:
t->bf=EH; taller=false;
break;
case EH:
t->bf=RH; taller =true;
break;
case RH:
RightBalance(t); taller=false;
break;
}
}
}
}
return 1;
}
Status Showtree(Bitree t)
{
if(t)
{
if(Showtree(t->lchild))
{
printf("%d\n",t->data);
if(Showtree(t->rchild))
return Ok;
}
}
else return Ok;
}
void main()
{
Bitree t;
int e; bool taller;
/*printf("请输入根节点");
creattree(t);*/
inital(t);
printf("请输入要插入的节点(输入0结束)");
scanf("%d",&e);
while(e!=0)
{
InsertAVL(t,e,taller);
scanf("%d",&e);
}
printf("平衡二叉树的中序序列为:\n");
Showtree(t);
getchar();
getchar();
}
//算法分析:1.平衡二叉树的要求:(1)它的左右子树都是平衡二叉树(2)它的左右子树的深度只差的绝对值不超过1
//2.在平衡二叉树上进行查找过程和排序树相同,进行比较的关键字个数不超过树的深度
//3.进行查找的时间复杂度为O(logn)
查找树-----平衡二叉树
原文作者:二叉查找树
原文地址: https://blog.csdn.net/q270274978/article/details/8484952
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/q270274978/article/details/8484952
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。