進行紅黑樹節點的插入時候我們必須結合紅黑樹的性質,要不是真的很容易忙半天卻發現寫的**漏洞百出不符合紅黑樹的性質
每個結點不是紅色就是黑色因為紅黑樹也是在搜尋二叉樹的基礎上,我先畫一顆紅黑二叉樹吧。根節點是黑色的
如果乙個節點是紅色的,則它的兩個孩子結點是黑色的
對於每個結點,從該結點到其所有後代葉結點的簡單路徑上,均 包含相同數目的黑色結點
每個葉子結點都是黑色的(此處的葉子結點指的是空結點
每個節點的指向是三個方向,但是這個畫起來好累啊,構造紅黑樹的時候一看也就明白了,這裡就說明一下啊。。。
#include using namespace std;
enum color;
templatestruct rbtreenode
rbtreenode* _pleft;
rbtreenode* _pright;
rbtreenode* _pparent;
v _value; // 節點值域
color _color; // 節點的顏色
};
這裡還是主要看一下插入吧,如果在把刪除看一下,估計要把部落格寫道半夜了。
紅黑樹的插入時候主要分三種情況,三種情況都涉及到顏色調整的,兩種都涉及到旋轉,所以紅黑樹必須是要研究三代的,這裡是必須把圖畫清楚的
還有新插入節點預設著色是紅色的,如果是黑色,每條路徑上黑色節點的個數都相等這一條很重要的性質直接就違背了
我們用pcur代表當前節點的位置,用p代表父節點的位置,用g代表祖父節點,用u代表叔父節點
templateclass rbtree
bool insert(const v& value)
else
// 插入新節點
pcur = new node(value);
if (value < pparent->_value)
pparent->_pleft = pcur;
else
pparent->_pright = pcur;
pcur->_pparent = pparent;
// 更新節點的顏色,滿足紅黑樹性質
// ....
while (pparent && red == pparent->_color)
else
// 情況二
rotateright(grandfather);
swap(grandfather->_color, pparent->_color);}}
else
else
rotateleft(grandfather);
swap(grandfather->_color, pparent->_color);}}
}} _phead->_pleft = leftmost();
_phead->_pright = rightmost();
_phead->_pparent->_color = black;
return true;
}
插入除了分情況旋轉外,其他操作其實還是模擬搜尋二叉樹的。
bool isvalidrbtree()
// 獲取左左側路徑中黑色節點的個數
size_t blackcount = 0;
pnode pcur = proot;
while (pcur)
size_t pathcount = 0;
return _isbalidrbtree(proot, pathcount, blackcount);
} bool _isbalidrbtree(pnode proot, size_t pathcount, size_t blackcount)
if (black == proot->_color)
pathcount++;
if (nullptr == proot->_pleft && nullptr == proot->_pright)
}return _isbalidrbtree(proot->_pleft, pathcount, blackcount) &&
_isbalidrbtree(proot->_pright, pathcount, blackcount);
} void _inorder(pnode proot) }
pnode& getroot()
pnode leftmost()
pnode rightmost()
void rotateleft(pnode pparent) }
void rotateright(pnode pparent)
}
是否是紅黑二叉樹驗證時候需要驗證的性質其實主要是四條,但是最主要驗證的還是每條路徑上黑色節點的數量是否相等。驗證相等時候我們選取最左側的路徑作為對比路徑,計算出左側節點的黑色節點個數,然後與驗證路徑對比,如果相符就滿足。
#include using namespace std;
enum color;
templatestruct rbtreenode
rbtreenode* _pleft;
rbtreenode* _pright;
rbtreenode* _pparent;
v _value; // 節點值域
color _color; // 節點的顏色
};templateclass rbtree
bool insert(const v& value)
else
// 插入新節點
pcur = new node(value);
if (value < pparent->_value)
pparent->_pleft = pcur;
else
pparent->_pright = pcur;
pcur->_pparent = pparent;
// 更新節點的顏色,滿足紅黑樹性質
// ....
while (pparent && red == pparent->_color)
else
// 情況二
rotateright(grandfather);
swap(grandfather->_color, pparent->_color);}}
else
else
rotateleft(grandfather);
swap(grandfather->_color, pparent->_color);}}
}} _phead->_pleft = leftmost();
_phead->_pright = rightmost();
_phead->_pparent->_color = black;
return true;
} void inorder()
bool isvalidrbtree()
// 獲取左左側路徑中黑色節點的個數
size_t blackcount = 0;
pnode pcur = proot;
while (pcur)
size_t pathcount = 0;
return _isbalidrbtree(proot, pathcount, blackcount);
}private:
bool _isbalidrbtree(pnode proot, size_t pathcount, size_t blackcount)
if (black == proot->_color)
pathcount++;
if (nullptr == proot->_pleft && nullptr == proot->_pright)
}return _isbalidrbtree(proot->_pleft, pathcount, blackcount) &&
_isbalidrbtree(proot->_pright, pathcount, blackcount);
} void _inorder(pnode proot) }
pnode& getroot()
pnode leftmost()
pnode rightmost()
void rotateleft(pnode pparent) }
void rotateright(pnode pparent) }
private:
pnode _phead;
};void testrbtree()
; rbtreet;
for (auto e : array)
t.insert(e);
t.inorder();
if (t.isvalidrbtree())
else }
int main()
驗證一下
二叉搜尋樹 紅黑樹節點插入
1.紅黑樹的概念 紅黑樹是一棵二叉搜尋樹,它在每個節點上增加乙個儲存位來表示節點的顏色,可以是red或black,通過對任何一條從根節點到葉子節點上的間單路徑來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近視平衡。2.紅黑樹的性質 滿足上訴性質的二叉搜尋樹是二叉搜尋樹 3.具體插入節點的步驟 ...
二叉樹節點的插入與刪除
1 先定義乙個二叉樹節點 templateclass treenode treenode t ele 2 再進行二叉樹的插入以建立乙個二叉樹 若二叉樹為空,直接建立根節點儲存資料即可 若不為空,當新元素小於父節點時,根據二叉搜尋樹特點,需要作為父節點左子樹,反之作為右子樹 bool insert t...
列印二叉樹節點
從上往下列印出二叉樹的每個節點,同層節點從左至右列印。條件反射地想通過遞迴解決,結果硬是沒有找到合適的解決思路,也許遞迴的方式不是很適合這種型別的題目吧 利用佇列的先進先出 fifo 特性解決。每從佇列頭部獲取乙個節點,就將該節點的左右子節點存入佇列的尾部。如此往復,直至隊列為空。這篇部落格內的和 ...