【C++】AVLTree

AVL树的概念

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。
在这里插入图片描述
因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
一棵AVL树或者是空树:
1.它的左右子树都是AVL树
2.左右子树的高度差绝对值不超多 1(-1 / 0 / 1)(简称平衡因子 = 右子树的高度 - 左子树的高度)

在这里插入图片描述
增删查改:高度次 -> O(logN)
满二叉树: 2^h - 1 = N
AVL树 : 2^h - x = N
X范围: [1 , 2^(h-1)-1]

AVL树节点的定义和AVL树的插入

AVL == 高度平衡的二叉搜索树
平衡不是相等,而是高度差不超过1;
在这里插入图片描述
在这里插入图片描述
1.新增在左,parent平衡因子减减
2.新增在右,parent平衡因子加加
在这里插入图片描述
3.更新后parent平衡因子 == 0,说明parent所在的子树高度不变,不会影响祖先节点,不用再继续沿着root的路径向上跟新.
4.更新后parent平衡因子 == 1 or -1,说明parent的所在子树的高度发生变化,会影响祖先,需要继续沿着到root节点的路径向上更新。
在这里插入图片描述
5.更新后parent平衡因子 == 2 or -2, 说明parent所在的子树高度变化且不平衡,需要对parent所在子树进行旋转,让他平衡。

AVL树的旋转

如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:
旋转的时候需要注意的问题:
1.保持他是搜索树
2.变成平衡树且降低这个子树的高度
3.旋转后更新平衡因子

左单旋

在这里插入图片描述
核心操作:
parent -> right = cur-> left
cur -> left = parent
在这里插入图片描述

右单旋

在这里插入图片描述
核心操作:
parent -> left = cur -> right
cur->right = parent

在这里插入图片描述

左右双旋和右左双旋

左右双旋

新节点插入较高左子树的右侧左单旋右单旋
在这里插入图片描述
核心操作:
左单旋
cur -> right = curright->left
curright->left = cur
curright->parent = cur->parent
cur->parent = curright
右单旋
parent->left = curright->right
curright->right = parent;
currigjt->parent = parent->parent
parent->parent = curright
在这里插入图片描述
因为双旋的原因,平衡因子会因为插入位置的不同发生不同变化:
如果新插入节点在较高左子树的右侧,则记录cur->right的平衡因子
插入在较高右子树的左侧,则记录cur->left的平衡因子
如:

int bf = curright->_bf;

如果bf0,则cur和curright和parent都为0;
如果bf
1,则cur->bf = -1, curright和parent的bf为0;
如果bf==-1,则cur和curright的bf为0,parent->bf = 1;

		if (bf == 0)
		{
			cur->_bf = 0;
			curright->_bf = 0;
			Parent->_bf = 0;
		}
		else if (bf == -1)
		{
			cur->_bf = 0;
			curright->_bf = 0;
			Parent->_bf = 1;
		}
		else if (bf == 1)
		{
			cur->_bf = -1;
			curright->_bf = 0;
			Parent->_bf = 0;
		}
		else
		{
			assert(false);
		}

而右左双旋则是跟左右双旋差不多只是顺序不同,就不做过多追述了;

AVL树的删除

因为AVL树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,只不错与删除不同的时,删除节点后的平衡因子更新,最差情况下一直要调整到根节点的位置。
在这里插入图片描述
如果平衡因子更新为0,则需要一直向上更新
在这里插入图片描述
如果平衡因子更新为-2/2,则需要根据情况旋转

在这里插入图片描述
当parent平衡因子为1/-1则不需要继续向上更新

AVL树的性能

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 l o g 2 ( N ) log_2 (N) log2(N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值