AVL树

参考文献

https://www.cnblogs.com/skywang12345/p/3576969.html
严蔚敏老师的《数据结构》

特别感谢skywang12345大佬帮助我理解AVL树。
复制了文章中的某些图片和源码实现,若冒犯,请联系本人删除。

特点

  1. 是二叉搜索树(BST)
  2. 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;
}

删除

见参考文献

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值