AVL树(高度平衡的二叉搜索树)平衡因子的调节和旋转

1.什么叫AVL树?

                   AVL树又称为高度平衡的二叉搜索树,它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度(尽量使这棵树保持为完全二叉树,这样就能提高搜索效率)。

2.AVL树的性质

       (1)左子树和右子树的高度之差的绝对值不超过1

          (2) 树中的每个左子树和右子树都是AVL树  

          (3) 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子  树的高度)


3.AVL树节点的定义
template <typename K,typename V>
struct AVLTreeNode
{
	K _key;
	V _value;
	int _bf; //平衡因子,只能取值为-1,1,0
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;
	AVLTreeNode(const K& key, const V& value)
		:_key(key)
		, _value(value)
		, _bf(0)
		, _left(NULL)
		, _right(NULL)
		, _parent(NULL)
	{}
};



4.AVL树左单旋的情况



对应代码实现:

void _RotateL(Node* &parent)
	{
		//1.将要修改的结点标记起来
		Node* SubR = parent->_right;
		Node* SubRL = SubR->_left;
		Node* pparent = parent->_parent;
		//2.重新链上SubR结点
		SubR->_left = parent;
		SubR->_parent = pparent;
		SubR->_bf = 0;
		//4.重新链上parent结点
		parent->_right = SubRL;
		parent->_parent = SubR;
		parent->_bf = 0;
		//5.改变pparent的指向结点
		if (pparent == NULL)
			_root = SubR;
		else if (pparent->_left == parent)
			pparent->_left = SubR;
		else
			pparent->_right = SubR;
		//4.重新链上SubRL结点
		if (SubRL != NULL)
			SubRL->_parent = parent;
		
	}



5.AVL树右单旋的情况


对应的代码实现:

	void _RotateR(Node* &parent)
	{
		//1.将要修改的结点标记起来
		Node* SubL = parent->_left;
		Node* SubLR = SubL->_right;
		Node* pparent = parent->_parent;
		//2.重新链上SubL结点
		SubL->_right = parent;
		SubL->_parent = parent->_parent;
		SubL->_bf = 0;
		//3.重新链上parent结点
		parent->_left = SubLR;
		parent->_parent = SubL;
		parent->_bf = 0;
		//4.改变pparent的指向结点
		if (pparent == NULL)
			_root = SubL;
		else if (pparent->_left == parent)
			pparent->_left = SubL;
		else
			pparent->_right = SubL;
		//5.重新链上SubRL结点
		if (SubLR != NULL)
			SubLR->_parent = parent;
	}


6.AVL树平衡因子的调节

     (1)插入的数据只能影响祖先结点的平衡因子;
    
     (2)当某个平衡因子从0变成1或者-1,需要继续调整祖先结点的平衡因子,直到根节点;
     
     (3)当某个平衡因子从-1或者1变成0,则不需要调整祖先的平衡因子了,因为平衡因子在插入数据之后变成0,证明整棵树的高度没有发生变化;


     (4)当平衡因子在插入数据之后变成-2或者2,需要通过旋转来降低它的高度,使它继续保持AVL树的性质

7.AVL树进行左右双旋的情况(注意平衡因子的调节




代码实现:

	void _RotateLR(Node* &parent)
	{
		//双旋的时候在某些情况下会导致bf发生异常
		Node* SubL = parent->_left;
		Node* SubLR = SubL->_right;
		int bf = SubLR->_bf;
		_RotateL(parent->_left);
		_RotateR(parent);
		if (bf == -1)
		{
			parent->_bf = 1;
			SubL->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = 0;
			SubL->_bf = -1;
		}
		else
		{
			SubL->_bf = parent->_bf = 0;
		}
		SubLR->_bf = 0;
	}

8.同样的方法可以得到右左双旋时平衡因子的变化


                  (1)SubRL->_bf==0   parent->_bf=SubR->_bf=0;

  (2)SubRL->_bf==-1  parent->_bf=0  SubR->_bf=1;

  (3)SubRL->_bf==1   parent->_bf=-1 SubR->_bf=0;

代码实现:
	void _RotateRL(Node* &parent)
	{
		Node* SubR = parent->_right;
		Node* SubRL = SubR->_left;
		int bf = SubRL->_bf;
		_RotateR(parent->_right);
		_RotateL(parent);
		if (bf == 1)
		{
			parent->_bf = -1;
			SubR->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 0;
			SubR->_bf = 1;
		}
		else
		{
			SubR->_bf = parent->_bf = 0;
		}
		SubRL->_bf = 0;
	}






  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值