C++?AVL樹的兩單旋和兩雙旋的項目實踐
如果在一棵原本是平衡的AVL樹中插入一個新節(jié)點,可能造成不平衡,此時必須調(diào)整樹的結(jié)構(gòu),使之平衡化。根據(jù)節(jié)點插入位置的不同,AVL樹的旋轉(zhuǎn)分為四種。
1. 新節(jié)點插入較高左子樹的左側(cè)---左左:右單旋

a/b/c分別是高度為h的AVL子樹
上圖在插入前,AVL樹是平衡的,新節(jié)點插入到30的左子樹(注意:此處不是左孩子)中,30左子樹增加了一層,導(dǎo)致以60為根的二叉樹不平衡,要讓60平衡,只能將60左子樹的高度減少一層,右子樹增加一層,即將左子樹往上提,這樣60轉(zhuǎn)下來,因為60比30大,只能將其放在30的右子樹,而如果30有右子樹,右子樹根的值一定大于30,小于60,只能將其放在60的左子樹,旋轉(zhuǎn)完成后,更新節(jié)點的平衡因子即可。在旋轉(zhuǎn)過程中,有以下幾種情況需要考慮:
1. 30節(jié)點的右孩子可能存在,也可能不存在
2. 60可能是根節(jié)點,也可能是子樹
如果是根節(jié)點,旋轉(zhuǎn)完成后,要更新根節(jié)點
如果是子樹,可能是某個節(jié)點的左子樹,也可能是右子樹
代碼
//右單旋
void RotateR(Node* parent)
{
Node* SubL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
{
subL->_right = parent;
}
subL->_right = parent;
Node* ppnode = parent->_parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = subL;
}
else
{
ppnode->_right = subL;
}
subL->_parent = ppnode;
}
parent->_bf = 0;
subL->_bf = 0;
}2. 新節(jié)點插入較高右子樹的右側(cè)---右右:左單旋

左單旋與右單旋的操作類似,只有左右節(jié)點的區(qū)別
代碼
//左單旋
void RotateL(Node* parent)
{
Node* SubR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subR->_left = parent;
}
subR->_left = parent;
Node* ppnode = parent->_parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = subR;
}
else
{
ppnode->_right = subR;
}
subR->_parent = ppnode;
}
parent->_bf = 0;
subR->_bf = 0;
}3. 新節(jié)點插入較高左子樹的右側(cè)---左右:先左單旋再右單旋

參考30和60的相對位置,將雙旋變成單旋后再旋轉(zhuǎn),即:先對30進行左單旋,然后再對90進行右單旋,旋轉(zhuǎn)完成后再考慮平衡因子的更新。
代碼
//左右單旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == 1)
{
parent->_bf = 0;
subL->_bf = 0;
subLR->_bf = 1;
}
else if (bf == -1)
{
parent->_bf = 0;
subL->_bf = -1;
subLR->_bf = 0;
}
else if(bf==0)
{
parent->_bf = 0;
subL->_bf = 0;
subLR->_bf = 0;
}
else
{
assert(false);
}
}4. 新節(jié)點插入較高右子樹的左側(cè)---右左:先右單旋再左單旋

代碼
//右左單旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
if (bf == 1)
{
parent->_bf = 0;
subR->_bf = 0;
subRL->_bf = 1;
}
else if (bf == -1)
{
parent->_bf = 0;
subR->_bf = -1;
subRL->_bf = 0;
}
else if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
subRL->_bf = 0;
}
else
{
assert(false);
}
}總結(jié):
假如以pParent為根的子樹不平衡,即pParent的平衡因子為2或者-2,分以下情況考慮:
1. pParent的平衡因子為2,說明pParent的右子樹高,設(shè)pParent的右子樹的根為pSubR。
當pSubR的平衡因子為1時,執(zhí)行左單旋。
當pSubR的平衡因子為-1時,執(zhí)行右左雙旋。
2. pParent的平衡因子為-2,說明pParent的左子樹高,設(shè)pParent的左子樹的根為pSubL。
當pSubL的平衡因子為-1是,執(zhí)行右單旋。
當pSubL的平衡因子為1時,執(zhí)行左右雙旋。
旋轉(zhuǎn)完成后,原pParent為根的子樹個高度降低,已經(jīng)平衡,不需要再向上更新。
到此這篇關(guān)于C++ AVL樹的兩單旋和兩雙旋的項目實踐的文章就介紹到這了,更多相關(guān)C++ AVL樹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)LeetCode(133.克隆無向圖)
這篇文章主要介紹了C++實現(xiàn)LeetCode(133.克隆無向圖),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
linux根據(jù)pid獲取進程名和獲取進程pid(c語言獲取pid)
status文件,第一行的Name即為進程名,C程序?qū)崿F(xiàn)根據(jù)PID獲取進程名和根據(jù)進程名獲取PID,大家參考使用吧2013-12-12
C++ Custom Control控件向父窗體發(fā)送對應(yīng)的消息
這篇文章主要介紹了C++ Custom Control控件向父窗體發(fā)送對應(yīng)的消息的相關(guān)資料,需要的朋友可以參考下2015-06-06
關(guān)于函數(shù)傳參問題(指針傳參,值傳參,引用傳參)
這篇文章主要介紹了關(guān)于函數(shù)傳參問題(指針傳參,值傳參,引用傳參),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
C語言基于循環(huán)鏈表解決約瑟夫環(huán)問題的方法示例
這篇文章主要介紹了C語言基于循環(huán)鏈表解決約瑟夫環(huán)問題的方法,簡單描述了約瑟夫環(huán)問題并結(jié)合實例形式分析了C語言使用循環(huán)鏈表解決約瑟夫環(huán)問題的具體操作技巧,需要的朋友可以參考下2018-01-01
OpenCV數(shù)字圖像處理基于C++之圖像形態(tài)學(xué)處理詳解
OpenCV是一款由Intel公司俄羅斯團隊發(fā)起并參與和維護的一個計算機視覺處理開源軟件庫,支持與計算機視覺和機器學(xué)習相關(guān)的眾多算法,下面這篇文章主要給大家介紹了關(guān)于OpenCV數(shù)字圖像處理基于C++之圖像形態(tài)學(xué)處理的相關(guān)資料,需要的朋友可以參考下2022-12-12

