紅黑樹是一種自平衡二叉查找樹,能夠保證在最壞情況下基本動(dòng)態(tài)集合操作的時(shí)間復(fù)雜度為O(logn),在實(shí)際應(yīng)用中使用較為廣泛,JavaScript也提供了實(shí)現(xiàn)紅黑樹的方法。
紅黑樹和普通二叉查找樹最大的不同就在于它的自平衡特性,紅黑樹的每個(gè)節(jié)點(diǎn)都標(biāo)記著顏色,可以是紅色或者黑色,通過不斷調(diào)整紅色節(jié)點(diǎn)和黑色節(jié)點(diǎn)的位置來達(dá)到平衡。紅黑樹的基本規(guī)則如下:
1. 每個(gè)節(jié)點(diǎn)是紅色或者黑色 2. 根節(jié)點(diǎn)是黑色 3. 每個(gè)葉子節(jié)點(diǎn)是黑色的空節(jié)點(diǎn)(NIL節(jié)點(diǎn)) 4. 如果一個(gè)節(jié)點(diǎn)是紅色的,則它的子節(jié)點(diǎn)必須是黑色的 5. 從任一節(jié)點(diǎn)到其每個(gè)葉子節(jié)點(diǎn)的所有路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)
舉個(gè)例子,如下圖所示是一顆紅黑樹,其中黑色節(jié)點(diǎn)表示普通節(jié)點(diǎn),紅色節(jié)點(diǎn)表示需要調(diào)整的節(jié)點(diǎn),調(diào)整規(guī)則如下:
1. 如果插入的節(jié)點(diǎn)是根節(jié)點(diǎn),則標(biāo)記為黑色 2. 如果插入節(jié)點(diǎn)的父節(jié)點(diǎn)是黑色,則不需要調(diào)整 3. 如果插入節(jié)點(diǎn)的父節(jié)點(diǎn)是紅色,則需要繼續(xù)判斷父節(jié)點(diǎn)的兄弟節(jié)點(diǎn): 3.1. 如果父節(jié)點(diǎn)是左子節(jié)點(diǎn),則判斷右兄弟節(jié)點(diǎn)的顏色: 3.1.1. 如果右兄弟節(jié)點(diǎn)是紅色,則需要進(jìn)行顏色轉(zhuǎn)換,父節(jié)點(diǎn)和右兄弟節(jié)點(diǎn)變?yōu)楹谏娓腹?jié)點(diǎn)變?yōu)榧t色 3.1.2. 如果右兄弟節(jié)點(diǎn)是黑色,則需要判斷插入節(jié)點(diǎn)是否是右子節(jié)點(diǎn): 3.1.2.1. 如果是,則進(jìn)行左旋操作(將父節(jié)點(diǎn)變?yōu)楦?jié)點(diǎn),并將祖父節(jié)點(diǎn)作為它的右子節(jié)點(diǎn)) 3.1.2.2. 如果不是,則進(jìn)行左右旋操作(先將插入節(jié)點(diǎn)作為父節(jié)點(diǎn)的子節(jié)點(diǎn),再進(jìn)行左旋操作) 3.2. 如果父節(jié)點(diǎn)是右子節(jié)點(diǎn),則按照上述規(guī)則進(jìn)行對稱的操作
對于刪除節(jié)點(diǎn)操作,同樣需要進(jìn)行類似的調(diào)整操作,具體規(guī)則如下:
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)有兩個(gè)子節(jié)點(diǎn),則將該節(jié)點(diǎn)的后繼節(jié)點(diǎn)替代原有節(jié)點(diǎn),并將后繼節(jié)點(diǎn)從樹中刪除 4. 如果刪除節(jié)點(diǎn)顏色為紅色,則不需要調(diào)整 5. 如果刪除節(jié)點(diǎn)顏色為黑色,則需要繼續(xù)判斷刪除節(jié)點(diǎn)的兄弟節(jié)點(diǎn): 5.1. 如果兄弟節(jié)點(diǎn)為紅色,則進(jìn)行顏色轉(zhuǎn)換,兄弟節(jié)點(diǎn)和父節(jié)點(diǎn)的顏色互換,并進(jìn)行旋轉(zhuǎn)操作 5.2. 如果兄弟節(jié)點(diǎn)為黑色,并且它的兩個(gè)子節(jié)點(diǎn)都是黑色,則將兄弟節(jié)點(diǎn)標(biāo)記為紅色,并對父節(jié)點(diǎn)進(jìn)行調(diào)整 5.3. 如果兄弟節(jié)點(diǎn)為黑色,并且它的左子節(jié)點(diǎn)是紅色,右子節(jié)點(diǎn)是黑色,則進(jìn)行左旋操作,并繼續(xù)判斷兄弟節(jié)點(diǎn) 5.4. 如果兄弟節(jié)點(diǎn)為黑色,并且它的右子節(jié)點(diǎn)是紅色,則進(jìn)行右旋操作,并將兄弟節(jié)點(diǎn)變?yōu)榧t色,左子節(jié)點(diǎn)變?yōu)楹谏龠M(jìn)行左旋操作
紅黑樹的優(yōu)點(diǎn)在于能夠保證最壞情況下的時(shí)間復(fù)雜度,同時(shí)對于增刪操作,調(diào)整次數(shù)相對較少,故相較于AVL樹來說,紅黑樹更適用于大量插入、刪除操作的應(yīng)用場景。