平衡搜尋樹中的左單旋&右單旋&雙旋
阿新 • • 發佈:2019-01-06
本文要點:
平衡搜尋樹的左單旋、右單旋、左右雙旋、右左雙旋
在平衡搜尋樹中進行插入結點時,有可能會破壞整棵樹的平衡。為了保證平衡不被破壞,就要對一些節點進行旋轉,從而來降低樹的高度,這樣也能保證樹的平衡。
一、左單旋:
(上圖中的▲結點有可能是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);
}