数据结构中的树 --- 红黑树
紅黑樹是一種幾近平衡的二叉搜索樹, 但不是AVL樹.
1 紅黑樹的一些特殊性質(zhì)
1.?每個(gè)節(jié)點(diǎn)皆為紅色或者黑色。
2.?根節(jié)點(diǎn)是黑色。
3.?每個(gè)葉子節(jié)點(diǎn)(NIL)是黑色(注意, 每個(gè)葉子節(jié)點(diǎn)必須都為空節(jié)點(diǎn), 也就是指針為nullptr, 無key值)。
4.?每個(gè)紅色結(jié)點(diǎn)的兩個(gè)子結(jié)點(diǎn)一定都是黑色。
5.?任意一結(jié)點(diǎn)到以其為根節(jié)點(diǎn)的樹的每個(gè)葉子結(jié)點(diǎn)的路徑都包含數(shù)量相同的黑結(jié)點(diǎn)。
2 紅黑樹的插入和刪除操作
2.1 插入操作
當(dāng)我們要插入一個(gè)key值的節(jié)點(diǎn)時(shí), 需要走以下步驟
1. 按照二叉搜索樹的插入操作規(guī)則插入節(jié)點(diǎn)(此時(shí)節(jié)點(diǎn)并無顏色, 但是我們要通過后續(xù)操作讓此時(shí)的樹變?yōu)榧t黑樹).
2. 把新插入的節(jié)點(diǎn)(如果不是根節(jié)點(diǎn)的話)置為紅色
原因如下:
根據(jù)性質(zhì)5, 如果將新插入的節(jié)點(diǎn)A置為黑色, 那么A需要有兩個(gè)黑色的子節(jié)點(diǎn)(空的), 那么其父節(jié)點(diǎn)到A的兩個(gè)葉子節(jié)點(diǎn)的路徑上就會有兩個(gè)黑色節(jié)點(diǎn)(包括A和A的子節(jié)點(diǎn)), 多出A到其他葉節(jié)點(diǎn)的1個(gè).
3. 如果當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)是紅色, 進(jìn)行"調(diào)整"(具體調(diào)整方法如下).
調(diào)整:
由于此時(shí)插入節(jié)點(diǎn)為紅色且其父節(jié)點(diǎn)也為紅色, 那么此時(shí)樹不滿足紅黑樹的性質(zhì)4, 那么就不是一棵紅黑樹, 那么需要讓其滿足性質(zhì)4. 如圖:
3.1 叔叔節(jié)點(diǎn)也是紅色
將父節(jié)點(diǎn)和叔叔節(jié)點(diǎn)均置為黑色, 若祖父節(jié)點(diǎn)不是根節(jié)點(diǎn), 將祖父節(jié)點(diǎn)置為紅色, 將當(dāng)前節(jié)點(diǎn)置為祖父節(jié)點(diǎn), 對當(dāng)前節(jié)點(diǎn)繼續(xù)進(jìn)行"調(diào)整"
如例題所示, 當(dāng)我們要插入key值為35的節(jié)點(diǎn):
- 發(fā)現(xiàn)需要插在50的左子節(jié)點(diǎn), 然后置為紅色:
- 發(fā)現(xiàn)35的父親50和叔叔節(jié)點(diǎn)75都為紅色, 那么把二者都置為黑色, 并把祖父節(jié)點(diǎn)60置為紅色:
- 當(dāng)前節(jié)點(diǎn)為60, 紅色, 其父節(jié)點(diǎn)40和叔叔節(jié)點(diǎn)120皆為紅色, 那么將二者置為黑色, 祖父節(jié)點(diǎn)為根節(jié)點(diǎn), 不變色:
3.2 叔叔節(jié)點(diǎn)為黑色, 且當(dāng)前節(jié)點(diǎn)是右孩子
當(dāng)前節(jié)點(diǎn)是紅色, 父節(jié)點(diǎn)也是紅色, 但是其叔叔節(jié)點(diǎn)是黑色, 且當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的右孩子, 那么就將父節(jié)點(diǎn)左旋.
3.3 叔叔節(jié)點(diǎn)為黑色, 且當(dāng)前節(jié)點(diǎn)是左孩子
當(dāng)前節(jié)點(diǎn)是紅色, 父節(jié)點(diǎn)也是紅色, 但是其叔叔節(jié)點(diǎn)是黑色, 且當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的左孩子, 那么就將父節(jié)點(diǎn)置為黑色, 將祖父節(jié)點(diǎn)置為紅色, 并將祖父節(jié)點(diǎn)右旋.
2.2 刪除操作
刪除操作, 跟二叉搜索樹的操作一樣, 先把節(jié)點(diǎn)刪除, 然后:
1. 如果節(jié)點(diǎn)是葉節(jié)點(diǎn), 那么直接刪除
2. 如果被刪除的節(jié)點(diǎn)只有一個(gè)子節(jié)點(diǎn), 那么子節(jié)點(diǎn)直接代替刪除節(jié)點(diǎn)位置
3. 如果被刪除節(jié)點(diǎn)有左右子節(jié)點(diǎn), 那么找出中序遍歷的后繼節(jié)點(diǎn), 把要?jiǎng)h除的節(jié)點(diǎn)的值更新為其后繼節(jié)點(diǎn)的值, 然后刪除后繼節(jié)點(diǎn)(注意, 其后繼節(jié)點(diǎn)必然是其右子樹的中序遍歷的第一個(gè)節(jié)點(diǎn), 也就是肯定不會有左子節(jié)點(diǎn), 但凡有左子節(jié)點(diǎn), 左子節(jié)點(diǎn)一定排在它本身前面, 所以被刪除的節(jié)點(diǎn)最多有一個(gè)子節(jié)點(diǎn), 可以按照1, 2情況對其進(jìn)行分析).
4. 如果刪除的節(jié)點(diǎn)位置是黑色節(jié)點(diǎn), 那么就需要進(jìn)行"調(diào)整"
調(diào)整:
調(diào)整還是根據(jù)刪除后的當(dāng)前情況進(jìn)行.
刪除節(jié)點(diǎn)后, 當(dāng)前樹可能會不符合紅黑樹的2,4,5性質(zhì), 也就是根節(jié)點(diǎn)為黑色, 紅色節(jié)點(diǎn)的子節(jié)點(diǎn)為黑色,?節(jié)點(diǎn)到該節(jié)點(diǎn)的子孫節(jié)點(diǎn)的所有路徑上包含相同數(shù)目的黑節(jié)點(diǎn). 此時(shí)我們需要觀察刪除的那個(gè)節(jié)點(diǎn)位置代替者的情況, 如果其原本為紅色, 直接將該位置置為黑色, 結(jié)束調(diào)整. 如果其原本為黑色且是該位置為根節(jié)點(diǎn), 也是不需要做什么, 結(jié)束掉.?
那么剩下的情況就是, 被刪除的節(jié)點(diǎn)為黑色, 且代替他位置的節(jié)點(diǎn)也為黑色, 且該位置不是根節(jié)點(diǎn), 那么有以下四種情況(假設(shè)當(dāng)前節(jié)點(diǎn)為刪除位置的節(jié)點(diǎn)):
https://www.jianshu.com/p/e136ec79235c
1. 兄弟節(jié)點(diǎn)為紅色
2. 兄弟節(jié)點(diǎn)為黑色, 且兄弟節(jié)點(diǎn)的子節(jié)點(diǎn)也都為黑色
3. 兄弟節(jié)點(diǎn)為黑色, 且兄弟節(jié)點(diǎn)左子為紅色, 右子為黑色
4. 兄弟節(jié)點(diǎn)為黑色, 且兄弟節(jié)點(diǎn)右子為紅色.
總結(jié)
以上是生活随笔為你收集整理的数据结构中的树 --- 红黑树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu 改linux密码忘了怎么办
- 下一篇: 自学java编译老是出错_为什么按照书上