数据结构---AVL树调整方法(详)

AVL树的调整整体分为两种:

  • 单旋转
  • 左单旋
  • 右单旋
  • 双旋转
  • 先左单旋,再右单旋
  • 先右单旋,再左单旋

数据结构---AVL树调整方法(详)_第1张图片例如:上图想要将值为40的结点插入到AVL树中,只能将其插入到值为50的左孩子结点。
数据结构---AVL树调整方法(详)_第2张图片这里的平衡因子为:右孩子树的高度减去左孩子树的高度。
由于AVL树的平衡因子为-1或1.因此,上图已经不满足AVL树的要求,所以要对其进行旋转调整。

单旋
一:右单旋

如何判断AVL树需要进行右单旋操作:新节点插入较高左子树的左侧,需要对其进行右单旋。

什么是较高左子树的左侧:

数据结构---AVL树调整方法(详)_第3张图片
上图中,左子树的高度为2,右子树的高度为1,所以当新结点插入左子树的左孩子下方即称为较高左子树的左侧。
数据结构---AVL树调整方法(详)_第4张图片上述两种情况统称为较高左子树的左侧。

如何调整:
数据结构---AVL树调整方法(详)_第5张图片
上图中,结点80的平衡因子,已经不满足要求,需要将80的平衡因子降低(平衡因子是左右子数高度差的绝对值,为了方便描述,我这里的平衡因子是用右子数的高度减去左子树的高度,这里说的降低平衡因子,是是降低其绝对值)。解决办法是:提较高子树的根结点。上图中较高子树的根结点为60
数据结构---AVL树调整方法(详)_第6张图片
在调成期间也需要考虑一些特殊的情况:
数据结构---AVL树调整方法(详)_第7张图片
例如这种单支的情况,也满足右旋条件。

**注意:**在进行指向调整的同时,记得双亲结点的调整,最终记得调整每个结点的平衡因子。

数据结构---AVL树调整方法(详)_第8张图片

//结合上图,Node是AVL树每个结点的结构体
void RotateR(Node* pParent) //右单旋,右侧的树高度降低
{
	Node* pSubL = pParent->_pLeft;
	Node* pSubLR = pSubL->_pRight;
	Node* pPParent = pParent->_pParent;

	pParent->_pLeft = pSubLR;
	if (pSubLR)
		pSubLR->_pParent = pParent;
	pSubL->_pRight = pParent;
	pSubL->_pParent = pPParent;
	pParent->_pParent = pSubL;
	if (pPParent == nullptr)
	{
		_pRoot = pSubL;
	}
	else 
	{
		if (pPParent->_pLeft == pParent)
			pPParent->_pLeft = pSubL;
		else if (pPParent->_pRight == pParent)
			pPParent->_pRight = pSubL;
	}

	pParent->_bf = pSubL->_bf = 0;
}
左单旋

左单旋:左子树高度降低,类似于右单旋的镜像。
什么情况下需要进行左单旋:插入结点插在较高右子树的右侧。
数据结构---AVL树调整方法(详)_第9张图片
解决办法:将较高右子树的根结点往上提。
数据结构---AVL树调整方法(详)_第10张图片
调整方法:
数据结构---AVL树调整方法(详)_第11张图片
注意:数据结构---AVL树调整方法(详)_第12张图片

void RotateL(Node* pParent)  //左单旋,左侧高度降低
{
	Node* pSubR = pParent->_pRight;
	Node* pSubRL = pSubR->_pLeft;
	Node* pPParent = pParent->_pParent;

	pParent->_pRight = pSubRL;
	if (pSubRL)
		pSubRL->_pParent = pParent;
	pSubR->_pLeft = pParent;
	pSubR->_pParent = pPParent;
	pParent->_pParent = pSubR;
	if (pPParent == nullptr)
	{
		_pRoot = pSubR;
	}
	else
	{
		if (pPParent->_pLeft == pParent)
			pPParent->_pLeft = pSubR;
		else
			pPParent->_pRight = pSubR;
	}

	pSubR->_bf = pParent->_bf = 0;
}
双旋
先右单旋,再左单旋

场景:插入结点在,较高右子树的左侧。
数据结构---AVL树调整方法(详)_第13张图片上述两种情况都满足,插入结点在较高右子树的左侧。
数据结构---AVL树调整方法(详)_第14张图片经过调整发现调整后的树,不满足AVL树的性质,但是满足AVL树,左单旋的条件,接着对其进行左单旋。
数据结构---AVL树调整方法(详)_第15张图片

先左单旋,再右单旋

插入结点在较高左子树的右侧。
数据结构---AVL树调整方法(详)_第16张图片调整过程:
数据结构---AVL树调整方法(详)_第17张图片

你可能感兴趣的:(数据结构---AVL树调整方法(详))