平衡二叉树(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;
}
在上述代码中,我们展示了如何实现平衡二叉树的基本操作,包括节点的插入、删除、树的平衡操作以及遍历操作。通过这些操作,我们可以有效地维护一个自平衡的二叉搜索树,提高了查找、插入和删除操作的效率。
希望本篇博客能帮助您更好地理解平衡二叉树的概念和实现细节。如果您有任何疑问或建议,请随时与我们分享。谢谢阅读!