提到紅黑樹,你是不是頭皮發麻,難搞哦😔,別害怕,我來教你分分鐘學會他
我們先來看一下紅黑樹的定義:
紅黑樹:
1) 每個節點顏色屬性非紅即黑
2) 根節點顏色一定是黑色的;
3) 如果一個節點是紅的,那麼它的兩兒子都是黑的;
4) 對於任意節點而言,其到葉子節點的每條路徑都包含相同數目的黑色節點數;(因爲所有葉子節點都會回到 nil 哨兵結點,故本文忽略哨兵結點)
根據上述定義,我們可以設置紅黑樹 node 屬性
------------------------------------------------------------------------------------
node
1.private RBNode leftchild; 左孩子
2.private RBNode rightchild; 右孩子
3.private RBNode parent; 父結點
4.private ColorType color; 顏色屬性
5.private int key; 關鍵字
紅黑樹 new 的結點顏色爲紅色。
關於代碼中的head結點 ???
自設的一個頭節點,方便根結點能順利帶入代碼,不用重新判斷,並且頭節點的左右孩子結點保存的是整棵樹的最值,從而能夠快速得到最值
--------------------------------------------------------------------------------------
上述屬性應該不用我多說了叭,說不多說,下邊進入正題,往紅黑樹中添加節點,我們應該怎樣高效的維護呢?
紅黑樹的添加需要做兩件事情:維護節點顏色要求;維護二叉搜索樹的特點,即key值 左<中<右
關於顏色的變換,吶我的妙招就是和他祖父節點的另一個孩子結點(也就是它的堂叔)結點顏色進行比較,來維護樹的顏色要求
關於樹的平衡旋轉,介個和二叉搜索樹中的旋轉一樣,有單旋和雙旋兩種可能。
爲了方便大家閱讀,我做成了兩張圖,供大家學習
我們來看一下代碼,adjustTree代碼,希望你能看着上邊的圖,自己搞一下啦,俗話說的好:師傅領進門,修行靠個人🤭
public boolean insertItem(int key){
RBNode par = head;
RBNode p = getRoot();
while( p != NIL && p.getKey() != key){
par = p;
//先找到父結點位置
p = key < p.getKey() ? p.getLeftchild(): p.getRightchild();
}
//如果插入的值存在,則返回false
if(p != null && p.getKey() == key)
return false;
p = new RBNode(key,par,RED);
//結點的維護
p.setLeftchild(NIL);
p.setRightchild(NIL);
if(par == head){
//根結點
head.setLeftchild(p);
head.setRightchild(p);
head.setParent(p);
}else {
//孩子結點
if (key < par.getKey()) {
par.setLeftchild(p);
//維護整棵樹的最值
if (key < head.getLeftchild().getKey()) {
head.setLeftchild(p);
}
} else {
par.setRightchild(p);
//維護整棵樹的最值
if (key > head.getRightchild().getKey()) {
head.setRightchild(p);
}
}
}
//調整樹的顏色
adjustTree(p);
count++;
return true;
}
教你幾個小妙招:
1.一個方法只做一個事
2.所有事情分步做,做到原子性(學編程的各位原子性不用我多解釋了叭