数据结构——平衡搜索树的左单旋&右单旋&双旋

引入:

在平衡搜索树中进行插入结点时,有可能会破坏整棵树的平衡。为了保证平衡不被破坏,就要对一些节点进行旋转,从而来降低树的高度,这样也能保证树的平衡。

一、左单旋:

数据结构——平衡搜索树的左单旋&右单旋&双旋

注:上图中的▲结点(叶子节点)有可能是NULL,也有可能不为空。

从图中可以看出,进行左单旋时:只是改变了parent的右指针以及subR的左指针指向。将subR的左子树(subRL)作为parent的右子树,并让parent作为subR的左子树。很明显,这样做就降低了这棵树的高度。

进行旋转时需要注意的两点:

  • 1、改变subRL->_parent指向时,需要判断subRL是否为NULL,如果为空,就不能对其解引用。

  • 2、parent是否为根节点?如果parent为根节点,那么旋转完成后只需将subR赋给根节点即可;但如果parent不为根节点,即parent是某一节点ppNode的子树,就要判断parent在ppNode的左还是右,这样才能确定subR的位置。

    void RotateLeft(Node* parent) //左单旋
    {
    Node* subR = parent->_right;
    Node* subRL = subR->_left;

     	parent->_right = subRL;	//先改变parent的右指针
     	if (subRL)	//subRL可能为NULL
     	{
     		subRL->_parent = parent;
     	}
    
     	Node* ppNode = parent->_parent;
     	subR->_left = parent;
     	parent->_parent = subR;
    
     	if (ppNode == NULL)
     	{
     		_root = subR;
     		subR->_parent = NULL;
     	}
     	else
     	{
     		//判断subR应链接在ppNode的左子树还是右子树
     		if (ppNode->_left == parent)
     			ppNode->_left = subR;
     		else
     			ppNode->_right = subR;
    
     		subR->_parent = ppNode;
     	}
     }
    

二、右单旋:

数据结构——平衡搜索树的左单旋&右单旋&双旋
同左单旋一样,右单旋转时:将subL的右子树结点赋给parent的左指针,并让parent自己作为subL的右子树

void RotateRight(Node* parent) //右单旋
{
Node* subL = parent->_left;
Node* subLR = subL->_right;

parent->_left = subLR;
if (subLR)
{
	subLR->_parent = parent;
}

Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;

if (ppNode == NULL)	//说明parent结点为根节点
{
	_root = subL;
	subL->_parent = NULL;
}
else
{
	//如果parent不为根节点,判断其在上一个结点的右还是左
	if (ppNode->_left == parent)
		ppNode->_left = subL;
	else
		ppNode->_right = subL;

	subL->_parent = ppNode;
}

}

三、左右双旋:

双旋:进行了两步单旋。
数据结构——平衡搜索树的左单旋&右单旋&双旋

void RotateLR(Node* parent)		//左右双旋
	{
		RotateLeft(parent->_left);
		RotateRight(parent);
 
	}

四、右左双旋:

数据结构——平衡搜索树的左单旋&右单旋&双旋

void RotateRL(Node* parent)		//右左双旋
{
	
	RotateRight(parent->_right);
	RotateLeft(parent);
 
}