1. 程式人生 > >平衡搜尋樹中的左單旋&右單旋&雙旋

平衡搜尋樹中的左單旋&右單旋&雙旋

本文要點:

平衡搜尋樹的左單旋、右單旋、左右雙旋、右左雙旋

在平衡搜尋樹中進行插入結點時,有可能會破壞整棵樹的平衡。為了保證平衡不被破壞,就要對一些節點進行旋轉,從而來降低樹的高度,這樣也能保證樹的平衡。

一、左單旋:


(上圖中的▲結點有可能是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);

	}