AVL Tree平衡二叉树

平衡二叉树(Balanced Binary Tree):空树或者任一结点左、右子树高度差的绝对值不超过1,即|BF(T)| <= 1

平衡因子(Balance Factor,简称BF):BF(T)=hL-hR,其中hL和hR分别为T的左、右子树的高度

插入结点或删除结点时,当BF的值大于2或者小于2的时候,使用不同的旋转,使得二叉树平衡:

1. 每插入一个结点都要检验一次树,是否是平衡树

2. 若是不是平衡树,从树的最深处开始旋转

3. 根据平衡因子的正负和添加结点的位置,使用不同的旋转方式:(此旋转方式是固定的)

    若结点的BF = 2时,且结点的左子树结点的BF = 1时,使用RotateLL(BF=2的结点)

    若结点的BF = 2时,且结点的左子树结点的BF = -1时,使用RotateLR(BF=2的结点)

    若结点的BF = -2时,且结点的左子树结点的BF = -1时,使用RotateRR(BF=-2的结点)

    若结点的BF = -2时,且结点的左子树结点的BF = 1时,使用RotateRL(BF=-2的结点)


完整的代码:

#include <iostream>
#include <cstdio>
using namespace std;

// AVLTree平衡二叉树(Balanced Binary Tree)/高度平衡的二叉查找树 
// 插入、删除 

typedef int DataType;
typedef struct node{
	DataType data;
	int bf;				// 平衡因子 
	struct node *lchild, *rchild;
}AVLNode, *AVLTree;

// 右单旋转(LL旋转): *a的左子树的左子树上 插入新结点 
void RotateLL(AVLNode *&a)
{
	AVLNode *b = a->lchild;
	a->lchild = b->rchild;
	b->rchild = a;
	b->bf = a->bf = 0;
	a = b;
}

// 左单旋转(RR旋转): *a的右子树的右子树上 插入新结点 
void RotateRR(AVLNode *&a)
{
	AVLNode *b = a->rchild;
	a->rchild = b->lchild;
	b->lchild = a;
	b->bf = a->bf = 0;
	a = b;
}

// 先左后右双旋转(LR旋转): *a的左子树的右子树上 插入新结点 
void RotateLR(AVLNode *&a)
{
	AVLNode *b = a->lchild, *c = b->rchild;
	b->rchild = c->lchild;				// 左单旋转 
	c->lchild = b;						// 左单旋转 
	if(c->bf <= 0)
		b->bf = 1;
	else
		b->bf = 0;
	a->lchild = c->rchild;				// 右单旋转 
	c->rchild = a;						// 右单旋转 
	if(c->bf == -1)
		a->bf = 0;
	else
		a->bf = -1;
	c->bf = 0;
	a = c;
}

// 先右后左双旋转(RL旋转): *a的右子树的左子树上 插入新结点 
void RotateRL(AVLNode *&a)
{
	AVLNode *b = a->rchild, *c = b->lchild;
	b->lchild = c->rchild;				// 右单旋转 
	c->rchild = b;						// 右单旋转 
	if(c->bf >= 0)
		b->bf = -1;
	else
		b->bf = 0;
	a->rchild = c->lchild;				// 左单旋转 
	c->lchild = a;						// 左单旋转 
	if(c->bf == 1)
		a->bf = 0;
	else
		a->bf = 1;
	c->bf = 0;
	a = c;
}


// 先序递归遍历 
void PreOrder(AVLTree root)
{
	if(root != NULL)
	{
		printf("%4d", root->data);
		PreOrder(root->lchild);
		PreOrder(root->rchild);
	}
}
void PreBF(AVLTree root)	// 先序遍历平衡因子 
{
	if(root != NULL)
	{
		printf("%4d", root->bf);
		PreBF(root->lchild);
		PreBF(root->rchild);
	}
}
void InOrder(AVLTree root)	// 中序递归遍历 
{
	if(root != NULL)
	{
		PreOrder(root->lchild);
		printf("%4d", root->data);
		PreOrder(root->rchild);
	}
}

// 计算树的平衡因子 
int count(AVLNode *r)
{
	if(r->lchild == NULL && r->rchild == NULL)
	{
		r->bf = 0;
		return 1;
	}
	else
	{
		int lhigh, rhigh;
		if(r->lchild != NULL)
		{
			lhigh = count(r->lchild);
		}
		else
			lhigh = 0;
		
		if(r->rchild != NULL)
		{
			rhigh = count(r->rchild);
		}
		else
			rhigh = 0;
		
		r->bf = lhigh - rhigh;		// 因子 = 左子树高度 - 右子树高度 
		if(lhigh > rhigh)
			return lhigh + 1;
		else
			return rhigh + 1;
	}
}

// 一个结点一个结点地添加/删除,然后调整,所以平衡因子不会超过2/-2 
// 在root树种,添加值为x的结点,并且调整成为平衡二叉树 
AVLNode* InsertAndBalance(AVLTree &root, DataType x)
{
	AVLNode *s, *p, *f;
	
	if(root == NULL)
	{
		root = new AVLNode;
		if(root == NULL)
			return NULL;
		root->data = x;
		root->bf = 0;
		root->lchild = NULL;
		root->rchild = NULL;
		return root;
	}
	else
	{
		if(x > root->data)
		{
			root->rchild = InsertAndBalance(root->rchild, x);
			
			count(root);	// 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子) 
			
			if(root->bf == 2)		// 如果不平衡,进行旋转 
			{
				if(root->lchild->bf == 1)
					RotateLL(root);
				else if(root->lchild->bf == -1)
					RotateLR(root);
				count(root);
			}
			else if(root->bf == -2)
			{
				if(root->rchild->bf == -1)
					RotateRR(root);
				else if(root->rchild->bf == 1)
					RotateRL(root);
				count(root);
			}
			
		}
		else if(x < root->data)
		{
			root->lchild = InsertAndBalance(root->lchild, x);
			
			count(root);	// 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子) 
			
			if(root->bf == 2)		// 如果不平衡,进行旋转 
			{
				if(root->lchild->bf == 1)
					RotateLL(root);
				else if(root->lchild->bf == -1)
					RotateLR(root);
				count(root);
			}
			else if(root->bf == -2)
			{
				if(root->rchild->bf == -1)
					RotateRR(root);
				else if(root->rchild->bf == 1)
					RotateRL(root);
				count(root);
			}
			
		}
		
	}
	
	return root;
}

// 在root树种,删除结点x,并且调整成为平衡二叉树 
AVLNode* RemoveAndBalance(AVLTree &root, DataType x)
{
	AVLNode *s, *p, *f;
	
	if(root == NULL)
	{
		return root;
	}
	else
	{
		if(x > root->data)
		{
			root->rchild = RemoveAndBalance(root->rchild, x);
			
			count(root);	// 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子) 
			
			if(root->bf == 2)		// 如果不平衡,进行旋转 
			{
				if(root->lchild->bf == 1)
					RotateLL(root);
				else if(root->lchild->bf == -1)
					RotateLR(root);
				count(root);
			}
			else if(root->bf == -2)
			{
				if(root->rchild->bf == -1)
					RotateRR(root);
				else if(root->rchild->bf == 1)
					RotateRL(root);
				count(root);
			}
			
		}
		else if(x < root->data)
		{
			root->lchild = RemoveAndBalance(root->lchild, x);
			
			count(root);	// 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子) 
			
			if(root->bf == 2)		// 如果不平衡,进行旋转 
			{
				if(root->lchild->bf == 1)
					RotateLL(root);
				else if(root->lchild->bf == -1)
					RotateLR(root);
				count(root);
			}
			else if(root->bf == -2)
			{
				if(root->rchild->bf == -1)
					RotateRR(root);
				else if(root->rchild->bf == 1)
					RotateRL(root);
				count(root);
			}
			
		}
		else if(x == root->data)
		{
			AVLNode *s, *f;
			if(root->lchild == NULL && root->rchild == NULL)	// 叶子的时候 
			{
				delete root;
				return NULL;
			}
			else if(root->lchild == NULL && root->rchild != NULL)
			{
				s = root->rchild;
				delete root;
				return s;
			}
			else if(root->lchild != NULL && root->rchild == NULL)
			{
				s = root->lchild;
				delete root;
				return s;
			}
			else if(root->lchild != NULL && root->rchild != NULL)
			{
				s = root->lchild;
				if(s->rchild != NULL)
				{
					while(s->rchild != NULL)
					{
						f = s;
						s = s->rchild;
					}
					f->rchild = NULL;
					root->data = s->data;
					if(s->lchild != NULL)
					{
						if(f->data > s->lchild->data)
							f->lchild = s->lchild;
						else
							f->rchild = s->lchild;
					}
				}
				else		// 左子树没有右结点时 
				{
					root->data = s->data;
					root->lchild = s->lchild;
				}
				delete s;
				return root;
			}
		}
	}
	
	return root;
}


int main()
{
	int high;
	AVLNode *s, *f;
	AVLTree root = NULL;
	InsertAndBalance(root, 53);
	InsertAndBalance(root, 17);
	InsertAndBalance(root, 9);
	InsertAndBalance(root, 45);
	InsertAndBalance(root, 23);
	InsertAndBalance(root, 78);
	InsertAndBalance(root, 65);
	InsertAndBalance(root, 66);
	InsertAndBalance(root, 67);
	//InsertAndBalance(root, 94);
	//InsertAndBalance(root, 81);
	//InsertAndBalance(root, 88);
	//high = count(root);
	//cout << "Tree high is " << high << endl;
	cout << "数值: ";
	PreOrder(root);
	cout << endl;
	cout << "因子: ";
	PreBF(root);
	cout << endl << endl;
	
	RemoveAndBalance(root, 45);
	RemoveAndBalance(root, 9);
	cout << "先序遍历: ";
	PreOrder(root);
	cout << endl;
	cout << "中序遍历: ";
	InOrder(root);
	cout << endl;
	cout << "平衡因子: ";
	PreBF(root);
	cout << endl << endl;
	
	RemoveAndBalance(root, 17);
	RemoveAndBalance(root, 53);
	InsertAndBalance(root, 94);
	cout << "先序遍历: ";
	PreOrder(root);
	cout << endl;
	cout << "中序遍历: ";
	InOrder(root);
	cout << endl;
	cout << "平衡因子: ";
	PreBF(root);
	cout << endl << endl;
	
	
	return 0;
}


运行结果:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值