查找树-----平衡二叉树

#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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞