数据结构——平衡树(AVL)

        平衡二叉树(AVL)的前提它得是有序二叉树,它的左右子树的高度差不超过1,而且它的所有子树也满足这个条件。那平衡树到底有什么意义呢,一切为效率服务:如果一个有序二叉树呈现接近单支状的链表,那么它的查找效率接近链表,因此只有达到平衡时它的查找效率最高。也可以理解为把有序的二叉树调整成一棵平衡树,所以核心就是调整的过程。

同样用链式结构表示,先构成数据项:

typedef struct TreeNode
{
	int data;
	struct TreeNode *left;
	struct TreeNode *right;
}TreeNode;

下面我们要对现有数据项结构的树进行操作,包括了调整平衡等相关操作:

创建结点

//创建结点
TreeNode *create_node(int data)
{
	TreeNode *node=malloc(sizeof(TreeNode));
	node->data=data;
	node->left=NULL;
	node->right=NULL;
	return node;
}

求高度

//求高度
int high_tree(TreeNode *root)
{
	if(NULL==root) return 0;
	int lh=high_tree(root->left);
	int rh=high_tree(root->right);
	return lh>rh?lh+1:rh+1;
}

检查左右子树是否平衡

//检查左右子树是否平衡
int is_balance(TreeNode *root)
{
	return high_tree(root->left)-high_tree(root->right);	
}

右旋转

//右旋转
TreeNode *right_rotate(TreeNode *x)
{
	TreeNode *y=x->left;
	TreeNode *t2=y->right;
	y->right=x;
	x->left=t2;
	return y;
}

左旋转

//左旋转
TreeNode *left_rotate(TreeNode *x)
{
	TreeNode *y=x->right;
	TreeNode *t2=y->left;
	y->left=x;
	x->right=t2;
	return y;
}

自动平衡

//自动平衡
TreeNode *auto_balance(TreeNode *x)
{
	if(NULL==x) return NULL;
	int lh=high_tree(x->left);
	int rh=high_tree(x->right);
	if(lh-rh > 1)
	{
		if(is_balance(x->left)>=0)
		{
			//右旋转
			x=right_rotate(x);	
		}
		else
		{
			//左旋转
			x->left=left_rotate(x->left);
			//右旋转
			x=right_rotate(x);
		}
	}

	if(rh-lh > 1)
	{
		if(is_balance(x->right)<=0)
		{
			x=left_rotate(x);	
		}
		else
		{
			x->right=right_rotate(x->right);
			x=left_rotate(x);
		}
	}
	return x;
}

插入

//插入
TreeNode *insert_tree(TreeNode *root,int data)
{
	if(NULL==root) return create_node(data);
	if(data<root->data) root->left=insert_tree(root->left,data);
	else root->right=insert_tree(root->right,data);
	root=auto_balance(root);
	return root;
}

前序遍历

//前序遍历
void preorder(TreeNode *root)
{
	if(NULL==root) return;
	printf("%d ",root->data);
	preorder(root->left);
	preorder(root->right);
}

中序遍历

//中序遍历
void midorder(TreeNode *root)
{
	if(NULL==root) return;
	midorder(root->left);
	printf("%d ",root->data);
	midorder(root->right);
}

删除

//删除
/*1、待删除的结点是叶子结点直接删除
2、待删除的结点左或右子树为空则使用非空子结点替换
3、待删除的结点左右子树非空,则根据左右子树的高度选择左边最大子结点或右边最小子结点进行替换*/
TreeNode *min_tree(TreeNode *root)
{
	TreeNode *min=root;
	while(min->left) min=min->left;
	return min;
}
TreeNode *max_tree(TreeNode *root)
{
	TreeNode *max=root;
	while(max->right) max=max->right;
	return max;
}
TreeNode *del_tree(TreeNode *root,int data)
{
	if(NULL==root) return NULL;
	if(data==root->data)
	{
		//左右子树为空
		if(NULL==root->left && NULL==root->right)
		{
			free(root);
			root=NULL;
			return NULL;
		}
		//左子树为空
		if(NULL==root->left)
		{
			TreeNode *temp=root->right;
			free(root);
			return temp;
		}
		//右子树为空
		if(NULL==root->right)
		{
			TreeNode *temp=root->left;
			free(root);
			return temp;
		}
		//左右子树都不为空
		int lh=high_tree(root->left);
		int rh=high_tree(root->right);
		if(lh>=rh)
		{
			TreeNode *node=max_tree(root->left);
			root->data=node->data;
			root->left=del_tree(root->left,root->data);
		}
		else
		{
			TreeNode *node=min_tree(root->right);
			root->data=node->data;
			root->right=del_tree(root->right,root->data);
		}
		return root;
	}
	if(data < root->data)
		root->left=del_tree(root->left,data);	
	else
		root->right=del_tree(root->right,data);
	root=auto_balance(root);
	return root;
}

大概就是这么些操作,测试:

int main(int argc,const char* argv[])
{
	TreeNode *root=NULL;
	for(int i=0;i<10;i++)
	{
		int data=rand()%100;
		root=insert_tree(root,data);
	}
	//preorder(root);
	printf("\n");
	midorder(root);
	printf("\n");
	del_tree(root,92);
	midorder(root);
		
	return 0;
}

over

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值