AVL树的旋转

一.AVL树的旋转
由于在插入新节点后可能会导致双亲的平衡因子变为2或-2,此时为了保证该树依然是AVL树,则要进行旋转;我们将AVL树的旋转分为左单旋,右单旋,左右双旋,右左双旋四种情况

情况一:左单旋
如果新节点插入在较高右子树的右侧,此时进行左单旋
在这里插入图片描述
在节点16的右侧插入节点后,根节点的平衡因子变为2,此时进行左单旋(降低右子树高度)
思想: parent变为subR的左子树,subRL变为parent的右子树
步骤:

  • 要旋转的节点为parent,subR为parent的右孩子,subRL为subR的左孩子
  • parent的右孩子指向subRL,如果subRL不为空,则subRL的父亲指向parent;subR的左孩子指向parent,parent的双亲指向subR
  • 如果parent是根节点,则subR此时变为根节点,否则让parent的双亲节点的孩子节点指向subR(要判断是左孩子还是右孩子),subR的双亲节点指向parent的双亲节点
  • 更新subR和parent的平衡因子都为0
    在这里插入图片描述

实现:

void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		Node* pparent = parent->_parent;
		parent->_right = subRL;
		if (subRL)
			subRL->_parent = parent;
		subR->_left = parent;
		parent->_parent = subR;
		if (parent == _root)
		{
			_root = subR;
			_root->_parent = nullptr;
		}
		else
		{
			if (pparent->_left == parent)
				pparent->_left = subR;
			else
				pparent->_right = subR;
			subR->_parent = pparent;
		}
		subR->_bf = parent->_bf = 0;
	}

情况二:右单旋
如果新节点插入在较高右左子树的左侧,此时进行右单旋
在这里插入图片描述
在节点7的左侧插入节点后,根节点的平衡因子变为-2,此时进行右单旋(降低左子树高度)
思想: parent变为subL的右子树,subLR变为parent的左子树
步骤:

  • parent为要旋转的节点,subL为parent的左孩子,subLR为subL的右孩子
  • parent的左孩子指向subLR,如果subLR存在,则它的双亲指向parent; subL的右孩子指向parent,parent的双亲结点指向subL;
  • 如果parent是根节点,那么subL此时变为根节点;否则,让parent的双亲结点指向subL(需要判断是左孩子还是右孩子),subL的双亲节点指向parent的双亲节点
  • 更新subL和parent的平衡因子为0
    在这里插入图片描述

实现:

void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		Node* pparent = parent->_parent;
		parent->_left = subLR;
		if (subLR)
			subLR->_parent = parent;
		subL->_right = parent;
		parent->_parent = subL;
		if (parent == _root)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (pparent->_left == parent)
				pparent->_left = subL;
			else
				pparent->_right = subL;
			subL->_parent = pparent;
		}
		subL->_bf = parent->_bf = 0;
	}

情况三:右左双旋
如果新节点插入在较高右子树的左侧,则先进行右单旋,再进行左单旋
在这里插入图片描述
在节点20的左侧插入节点后,节点7的平衡因子变为2,此时先对节点7的右子树进行右单旋,再对节点7进行左单旋
思想 :先对subR进行右单旋,再对parent进行左单旋
步骤:

  • 先对subR进行右单旋,保存subRL的平衡因子
  • 再对parent进行左单旋
  • 如果subRL的平衡因子为-1,则证明在它的左侧插入新节点,更新subR的平衡因子为1,parent的平衡因子为0
  • 如果subRL的平衡因子为1,则证明在它的右侧插入新节点,更新subR的平衡因子为-1,parent的平衡因子为-1
  • 更新subRL的平衡因子为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)
		{
			subR->_bf = 0;
			parent->_bf = -1;
		}
		else if (bf == -1)
		{
			subR->_bf = 1;
			parent->_bf = 0;
		}
		else if (bf == 0)
		{
			subR->_bf = parent->_bf = 0;
		}
		subRL->_bf = 0;
	}

情况四:左右双旋
如果新节点插入在较高左子树的右侧,则先进行左单旋,再进行右单旋
在这里插入图片描述
在节点15的左侧插入节点后,节点20的平衡因子变为-2,此时先对节点20的左子树进行左单旋,再对节点20进行右单旋
**思想:**先对subL进行左单旋,再对parent进行右单旋
步骤:

  • 先对subL进行左单旋,保存subLR的平衡因子
  • 再对parent进行右单旋
  • 如果subLR的平衡因子为-1,则证明在它的左侧插入新节点,更新subL的平衡因子为0,parent的平衡因子为1
  • 如果subLR的平衡因子为1,则证明在它的右侧插入新节点,更新subR的平衡因子为-1,parent的平衡因子为0
  • 更新subRL的平衡因子为0
    在这里插入图片描述

实现:

void RotateLR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		
		int bf = subLR->_bf;
		RotateL(parent->_left);
		RotateR(parent);
		if (bf == 1)
		{
			subL->_bf = -1;
			parent->_bf = 0;
		}
		else if (bf == -1)
		{
			subL->_bf = 0;
			parent->_bf = 1;
		}
		else if (bf == 0)
		{
			subL->_bf = parent->_bf = 0;
		}
		subLR->_bf = 0;
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值