参考文献
https://www.cnblogs.com/skywang12345/p/3576969.html
严蔚敏老师的《数据结构》
特别感谢skywang12345
大佬帮助我理解AVL树。
复制了文章中的某些图片和源码实现,若冒犯,请联系本人删除。
特点
- 是二叉搜索树(BST)
- AVL树中任何节点的两个子树的高度最大差别为1
源码实现
节点定义
typedef int Type;
typedef struct AVLTreeNode{
Type key; // 关键字(键值)
int height; // 以该节点为根节点的树,树的高度
struct AVLTreeNode *left; // 左孩子
struct AVLTreeNode *right; // 右孩子
}Node, *AVLTree;
调整
- LL旋转
- LR
- RR
- RL
LL旋转
分析:
- A的左子树的高度是h+1,右子树的高度是h-1,差了2
- 被破坏者是A,破坏者在A的左子树的左子树上,所以是LL旋转
/*
* LL:左左对应的情况(左单旋转)。
*
* 返回值:旋转后的根节点
*/
static Node* left_left_rotation(AVLTreeNode* A)
{
AVLTreeNode* B = A->left;
A->left = B->right;
B->right = A;
A->height = max(A->right->height, A->left->height) + 1;
B->height = max(B->left->height, A->height) + 1;
return B;//B成为了根节点
}
RR旋转
实现和LL旋转差不多。
LR旋转
LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡。
//LR旋转
static Node* left_right_rotation(AVLTree k3)
{
//先对k1做 RR 旋转
k3->left = right_right_rotation(k3->left);
//再对k3做 LL 旋转
return left_left_rotation(k3);
}
RL旋转
//RL旋转
static Node* right_left_rotation(AVLTree k1)
{
//LL旋转
k1->right = left_left_rotation(k1->right);
//RR旋转
return right_right_rotation(k1);
}
插入
案列分析
依次添加"3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9" 到AVL树中
代码实现
/*
* 将结点插入到AVL树中,并返回根节点
*
* 参数说明:
* tree AVL树的根结点,root
* key 插入的结点的键值
* 返回值:
* 根节点
*/
//递归实现
Node* avltree_insert(AVLTree tree, Type key)
{
if (tree == NULL)
{
// 新建节点
tree = avltree_create_node(key, NULL, NULL);
}
else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况
{
tree->left = avltree_insert(tree->left, key); //递归
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
{
if (key < tree->left->key) //意味着:新节点插到了左子树的左子树上
tree = left_left_rotation(tree); //LL旋转
else if (key > tree->left->key)//意味着:新节点插到了左子树的右子树上
tree = left_right_rotation(tree); //LR旋转
}
}
else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况
{
tree->right = avltree_insert(tree->right, key);
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
{
if (key > tree->right->key)
tree = right_right_rotation(tree);
else
tree = right_left_rotation(tree);
}
}
else //key == tree->key)
{
printf("添加失败:不允许添加相同的节点!\n");
}
tree->height = MAX( HEIGHT(tree->left), HEIGHT(tree->right)) + 1;
return tree;
}
删除
见参考文献