AVL树(平衡二叉搜索树)

1、AVL树(平衡二叉搜索树)的概念

 AVL树本质是一颗二叉搜索树。

但是对于普通的二叉搜索树,如果数据有序或者接近有序的时候,此时二叉搜索树就是一颗单边树了,此时搜索的效率就很低下。

两位俄罗斯的数学家G.M.Adelson-VelskiiE.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

由此:AVL树的概念,就是具有以下性质的一颗二叉搜索树:

1、要么是空树

2、左右子树均为AVL树

3、左右子树的高度差(平衡因子)的绝对值不超过1。---->因此AVL树也叫平衡二叉搜索树

1、1平衡因子(bf) 

如上:平衡因子(Balance Factor,简写为bf = 右子树高度 - 左子树高度

-1 <= bf <= 1

这两棵树不是AVL树哈。 

1、2区分AVL树

1、3AVL树的作用 

因此:一颗AVL树的结点数为N,那么其高度可保持在logN,因此,搜索的时间复杂度可以在O(logN)

2、AVL树结点的定义

template<class K, class V>
struct AVLTreeNode
{
	//拷贝构造
	AVLTreeNode(const pair<K, V>& val = pair < K, V)())
		:_kv(val)
		, _bf(0)
		,_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
	{}
	pair<K, V> _kv;//存储值
	int _bf;//平衡因子

	AVLTreeNode* _left;//左孩子
	AVLTreeNode* _right;//右孩子
	AVLTreeNode* _parent;//父结点
};

这里用<K,V>模型,来存储结点值。

3、AVL树的插入

因为AVL树就是一颗特殊的二叉搜索树,所以AVL树插入结点,可以看作:

1、按照二叉搜索树的方式,插入结点

2、调整平衡因子(旋转)

插入结点之前,所有结点的平衡因子有三种情况:-1,0,1。

插入之后,结点的bf会发生变化,也有三种情况

1、情况一:新插入结点的父结点(_parent)的_bf变为0。(由1/-1变到0)

2、情况二:新插入结点的父结点(_parent)的_bf变为1/-1。(由0变到1/-1)

当新结点的parent的_bf变为0时,我们需要查看parent的祖先结点的_bf的状态,如果|_bf|大于1了,就需要调整(旋转)。

3、情况三:新插入结点的父结点(_parent)的_bf变为2/-2。(由1/-1变到2/-2)

4、AVL树的旋转

4、1新结点插入到较高左子树左侧---右单旋

一定是高左子树的左侧,才对应右单选 

对于图中的右单旋,它的规则如下:

如图:

举例,理解:

由此,我们可以写出右单旋的代码:

	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		parent->_left = subLR;
		if (subLR != nullptr) subLR->_parent = parent;
		
		Node* p_parent = parent->_parent;//记录parent的父结点
		subL->_right= parent;
		parent->_parent = subL;

		if (p_parent == nullptr)//parent的父结点为nullptr,即parent为根结点
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else//parent的父结点不为空,即parent为某个结点的子结点
		{
			subL->_parent = p_parent;
			//看parent是p_parent的左孩子还是右孩子
			if (p_parent->_left == parent) p_parent->_left = subL;
			else p_parent->_right = subL;
		}
		subL->_bf = parent->_bf = 0;//bf置零
	}

注意:传入的这个parent是平衡因子发生错误的结点。

对于这个结点,它可能是根节点,也可能是某个结点的子结点,需要分类讨论。

4、2新结点插入到较高右子树右侧---左单旋

左单旋的旋转规则如下:

</

  • 25
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夹心宝贝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值