AVL树

AVL树作为搜索树的衍生其保存了搜索树原有的性质,并且加入了四种需旋转方式使树的的高度维持在一个较优的情况下,以此提升了搜索速度。

起满足:首先是一个搜索树,后通俗的说对其每一个节点的左右子树的高度差不能超过二,否则就要通过旋转操作改变现状。而在实际过程中节点一个一个加入,其左右子树最大差的绝对值在【0,2】内。

四种旋转:

在左子树的左子树上插入新节点使树不平衡(LL){红色为插入点}:


在右子树的右子树上插入新节点使树不平衡(RR){红色为插入点}


在左子树的左子树上插入新节点使树不平衡(LR){白色为插入点}:

这时要先对不平衡节点的下一节点进行RR旋转后对不平衡点进行LL型旋转


在左子树的左子树上插入新节点使树不平衡(RL){白色为插入点}:

这时要先对不平衡节点的下一节点进行LL旋转后对不平衡点进行RR型旋转



而对于旋转后的树高维护只需要在插入和修改后递归过程中进行维护。而且在旋转中除了每次直接参与的两个节点外其余的都是以子树的形式参加所以其高度不会发生改变也就没有维护的必要

在输出时采用中序遍历可以式输出的序列为由小至大的有序数列。

#include<stdio.h>
#include<stdlib.h>
typedef struct node{//节点定义 
	int height;//记录树高 
	int num;//关键字 
	struct node* l;//左儿子 
	struct node* r;//右儿子 
} Node;
Node* Insert(Node* tree,int num);//插入节点 
Node* DeNode(Node* tree,int num);//删除节点 
Node* rrRotate(Node *tree); //RR
Node* llRotate(Node *tree);	//LL 
Node* lrRotate(Node *tree);//RL 
Node* rlRotate(Node *tree); //RL 
int FonPioneer(Node *tree);//找到某节点的中序遍历前驱 
int reHeight(Node* tree);//返回以某节点为根的树的树高 ,若为空返回0 
int Getheight(Node* tree);//获得当前节点树高 ,若没有子树返回1
int Maxheight(int a,int b);//得到最大高度 
void printTree(Node* tree);//输出树(中序遍历) 
void DeTree(Node** ptree);//删除树 
int main()//测试函数(主函数)------------------------------------------------------------------flag 
{
	Node* head=NULL;
	int num;
	while(scanf("%d",&num)==1&&num!=-1)
		head=Insert(head,num);
	printf("树高:%d\n",reHeight(head));
	printTree(head);
	printf("\n");
	head=DeNode(head,20);//删除关键字为20的节点 
	printf("删除关键字为20的节点后树高:%d\n",reHeight(head));  
	printTree(head);
	DeTree(&head);
	return 0; 
}
void printTree(Node* tree)
{
	if(tree==NULL)	return;
	printTree(tree->l);
	printf("%d(%d) ",tree->num,tree->height);//输出节点权值和以该节点为根的树的高度 
	printTree(tree->r);
}
void DeTree(Node** ptree)
{
	if(ptree==NULL||*ptree==NULL)	return;
	DeTree(&((*ptree)->l));
	DeTree(&((*ptree)->r));
	free(*ptree);
	*ptree=NULL;	
}
Node* Insert(Node* tree,int num)
{
	if(tree==NULL)
	{
		tree=(Node *)malloc(sizeof(Node));
		if(tree==NULL)
		{
			printf("插入失败\n");
			return NULL;
		}
		tree->num=num;
		tree->l=NULL;
		tree->r=NULL;	
		tree->height=Getheight(tree);
	}else
	{
		if(num>tree->num)
		{
			tree->r=Insert(tree->r,num);
			tree->height=Getheight(tree);
			if(reHeight(tree->l)-reHeight(tree->r)==-2)
			{
				if(num<tree->r->num)
				{
					tree=rlRotate(tree);
				}else{
					tree=rrRotate(tree);
				}
			}
		}else{
			tree->l=Insert(tree->l,num);
			tree->height=Getheight(tree);
			if(reHeight(tree->l)-reHeight(tree->r)==2)
			{
				if(num>tree->l->num)
				{
					tree=lrRotate(tree);
				}else{
					tree=llRotate(tree);
				}
			}
		}
	}
	return tree;
}
int reHeight(Node* tree)
{
	if(tree==NULL)	return 0;
	else return tree->height; 
} 
int Getheight(Node* tree)
{
	if(tree==NULL)
		return 0;
	else{
		return Maxheight(reHeight(tree->l),reHeight(tree->r))+1;
	}
}
int Maxheight(int a,int b)
{
	return a>b?a:b;
}
Node* DeNode(Node* tree,int num)
{
	if(num==tree->num)//找到删除点 
	{
		if(tree->l==NULL&&tree->r!=NULL)//删除点为叶子 
		{
			Node *deltree=tree;
			tree=tree->r;
			free(deltree);
			deltree=NULL;
		}else if(tree->r==NULL&&tree->l!=NULL)//删除点只有左儿子 
		{
			Node *deltree=tree;
			tree=tree->l;
			free(deltree);
			deltree=NULL;
		}else if(tree->l==NULL&&tree->r==NULL)//删除点只有右儿子 
		{
			free(tree);
			tree=NULL;
		}else{
			int delnum=FonPioneer(tree->l);
			tree->num=delnum;
			tree->l=DeNode(tree->l,delnum);//删除该节点中序遍历前驱 
			tree->height=Getheight(tree);
			if(reHeight(tree->l)-reHeight(tree->r)==-2)
			{
				if(reHeight(tree->r->l)-reHeight(tree->r->r)==1)
				{
					tree=rlRotate(tree);
				}else{
					tree=rrRotate(tree);
				}
			}
		}
	}else if(num>tree->num)//未找到删除点 ,则其删除点一定是该节点子树中一节点,删除可能会改变树高所以应维护树高 
	{
		tree->r=DeNode(tree->r,num);
		tree->height=Getheight(tree); 
		if(reHeight(tree->l)-reHeight(tree->r)==2)
		{
			if(reHeight(tree->l->l)-reHeight(tree->l->r)==-1)
			{
				tree=lrRotate(tree);
			}else{
				tree=llRotate(tree);
			}
		}
	}
	else //未找到删除点 ,则其删除点一定是该节点子树中一节点,删除可能会改变树高所以应维护树高 
	{
		tree->l=DeNode(tree->l,num);
		tree->height=Getheight(tree);
		if(reHeight(tree->l)-reHeight(tree->r)==-2)
		{
			if(reHeight(tree->r->l)-reHeight(tree->r->r)==1)
			{
				tree=rlRotate(tree);
			}else{
				tree=rrRotate(tree);
			}
		}
	}
	return tree;
}
int FonPioneer(Node *tree)
{
	if(tree->r==NULL)
		return tree->num;
	return FonPioneer(tree->r);
}
Node* rrRotate(Node *tree)
{
	Node* newNode=tree->r;
	tree->r=newNode->l;
	newNode->l=tree;
	tree->height=Getheight(tree);
	newNode->height=Getheight(newNode);
	return newNode;
}
Node* llRotate(Node *tree)
{
	Node* newNode=tree->l;
	tree->l=newNode->r;
	newNode->r=tree;
	tree->height=Getheight(tree);
	newNode->height=Getheight(newNode);
	return newNode;
}
Node* lrRotate(Node *tree)
{
	tree->l=rrRotate(tree->l);
	return llRotate(tree);
}
Node* rlRotate(Node *tree)
{
	tree->r=llRotate(tree->r);
	return rrRotate(tree);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值