平衡二叉树(AVL树)介绍及实现代码详解

平衡二叉树(AVL树)介绍及实现代码详解

在这里插入图片描述

在本篇博客中,我们将介绍平衡二叉树(AVL树)的概念,并提供了一个用C语言实现的平衡二叉树代码示例。我们将详细解释代码中的每个部分,并展示如何插入节点、删除节点以及保持树的平衡。

什么是平衡二叉树(AVL树)?

平衡二叉树,又称AVL树,是一种自平衡的二叉搜索树。在AVL树中,任意节点的左子树和右子树的高度之差(平衡因子)不超过1。通过保持平衡,AVL树可以确保在最坏情况下的查找、插入和删除操作的时间复杂度为O(log n)。

代码实现详解

以下是一个用C语言实现的平衡二叉树代码示例,包括节点的创建、插入、删除以及树的平衡操作。
// 包含头文件和结构体定义

// 创建节点
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 dlr_show(TreeNode *root)
{
	if(NULL==root)return;
	printf("%d ",root->data);
	dlr_show(root->left);
	dlr_show(root->right);
}

//中序遍历
void ldr_show(TreeNode *root)
{
	if(NULL==root)return ;
	ldr_show(root->left);
	printf("%d ",root->data);
	ldr_show(root->right);
}
//后序遍历
void lrd_show(TreeNode *root)
{
	if(NULL==root)return;
	lrd_show(root->left);
	lrd_show(root->right);
	printf("%d ",root->data);
}
//查找结点 
TreeNode *find_node(TreeNode *root,int data)
{
	if(NULL==root)return NULL;
	if(data==root->data)return root;
	if(data<root->data)
		find_node(root->left,data);
	else 
		find_node(root->right,data);
}

//找到最大节点
TreeNode *_max_node(TreeNode *root)
{
	TreeNode *max=root;
	while(max->right)
	{
		max=max->right;
	}
	return max;
}

//找到最小节点
TreeNode *_min_node(TreeNode *root)
{
	TreeNode *min=root;
	while(min->left)
	{
		min=min->left;
	}
	return min;
}


// 删除节点
void del_tree(TreeNode *root, int data)
{
    TreeNode *parent = NULL;
    TreeNode *current = root;

    // 查找要删除的节点及其父节点
    while (current != NULL && current->data != data)
    {
        parent = current;
        if (data < current->data)
            current = current->left;
        else
            current = current->right;
    }

    if (current == NULL) // 没有找到要删除的节点
        return;

    if (current->left == NULL && current->right == NULL) // 删除的节点没有子节点
    {
        if (parent == NULL) // 删除的是根节点
        {
            free(root);
            root = NULL;
        }
        else if (parent->left == current)
        {
            free(parent->left);
            parent->left = NULL;
        }
        else
        {
            free(parent->right);
            parent->right = NULL;
        }
    }
    else if (current->left == NULL || current->right == NULL) // 删除的节点只有一个子节点
    {
        TreeNode *temp = (current->left != NULL) ? current->left : current->right;
        if (parent == NULL) // 删除的是根节点
        {
            free(root);
            root = temp;
        }
        else if (parent->left == current)
        {
            free(parent->left);
            parent->left = temp;
        }
        else
        {
            free(parent->right);
            parent->right = temp;
        }
    }
    else // 删除的节点有两个子节点
    {
        TreeNode *temp = _max_node(current->left); // 找到左子树中的最大节点或右子树中的最小节点
        current->data = temp->data; // 将找到的节点的值替换当前节点
        del_tree(current->left, temp->data); // 递归删除找到的节点
    }

    root = auto_balance(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);
    }
// 先序遍历显示树
dlr_show(root);
printf("\n");

// 删除节点并重新平衡树
del_tree(&root, 77);

// 再次先序遍历显示树
dlr_show(root);

return 0;
}

在上述代码中,我们展示了如何实现平衡二叉树的基本操作,包括节点的插入、删除、树的平衡操作以及遍历操作。通过这些操作,我们可以有效地维护一个自平衡的二叉搜索树,提高了查找、插入和删除操作的效率。

希望本篇博客能帮助您更好地理解平衡二叉树的概念和实现细节。如果您有任何疑问或建议,请随时与我们分享。谢谢阅读!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值