動畫 | 什麼是紅黑樹?(與2-3樹等價)

學習過2-3樹以後就知道應怎樣去理解紅黑樹了,若是直接看「算法導論」裏的紅黑樹的性質,是看不出因此然。咱們也看看一顆二分搜索樹知足紅黑的性質:html

1.每一個節點或是紅色的,或是黑色的;java

2.根節點是黑色的;算法

3.每一個葉子節點(NIL)是黑色的;segmentfault

4.若是一個節點是紅色的,則它的兩個子節點都是黑色的;ide

5.對每一個節點,從該節點到其全部後代葉子節點的簡單路徑上,均包含相同數目的黑色節點。學習

若是說前面4個還算理解,那第5個性質又是怎麼去理解呢?此時咱們藉着2-3樹去理解基本的紅黑樹,固然我會在後幾篇文章介紹2-3-4樹以及基於2-3-4樹的紅黑樹。動畫

拋開上面二分搜索樹知足紅黑的性質,咱們知道2-3樹不是二叉樹,咱們把它轉換成一顆二叉樹,2-節點很好轉,3-節點轉二叉卻有兩種,以下圖:spa

file

紅黑是指被指向節點的連接顏色,對於一顆2-3樹,由於3-節點的存在有不少不一樣的二叉樹的表示,因此咱們只考慮左傾的狀況。3d

左傾紅黑樹和2-3樹等價的定義

紅黑樹的定義是含有紅黑連接並知足下列條件的二分搜索樹:htm

1.紅連接均爲左鏈接;

2.沒有任何一個節點同時和兩條紅連接相連;

3.該樹是完美黑色平衡的,即任意空連接到根節點的路徑上的黑連接數量相同(和2-3樹等價的,任意節點到其葉子節點的高度都是相同的)。

由於2-3樹不存在永久的4-節點,4-節點終歸要分解的(在2-3-4樹中,爲了更好地插入和刪除,4-節點只存在於葉子節點,非葉子節點和2-3樹同樣的),因此在2-3樹中沒有任何一個節點能同時和兩條紅連接相連。對於第3條,2-3樹自己是絕對平衡的,將3-節點轉成二叉只增長了左紅連接,其餘黑連接沒有什麼變化,依然是黑色平衡的。

查找元素

查找命中和二分搜索樹同樣,從根節點開始,若是查找命中則返回,不然比它小的進行左遞歸查找,比它大的進行右遞歸查找,直到查找爲空。

寫插入元素和刪除元素以前,仍是要先介紹一下旋轉和顏色轉換。

旋轉

在插入或者刪除操做中可能會出現右傾或者兩條連續的紅連接,在向上變換的過程當中(恢復)都要調整爲左傾。

假設有一條紅色的右連接須要轉爲左連接,以下圖所示:

file

這個操做叫作左旋轉,右連接變成左連接,意味着被紅連接指向的節點會變成紅色,根節點默認是黑色。

右旋轉也同樣,不過在左傾紅黑樹中,只有出現兩條連續紅色的左鏈接纔會進行右旋轉,以下圖:

file

Code:左旋轉和右旋轉

file

顏色轉換

顏色轉換是用在臨時4-節點上的,無論是向下變換仍是向上變換。

file

Code:顏色轉換

file

插入元素

插入元素也須要先進行查找命中,查找未命中則在此節點(NIL)插入一個元素,是在紅黑樹底下插入一個紅色節點,插入元素默認是紅色節點。

若是紅黑樹目前是一顆空樹,能夠直接存儲一個元素做爲節點,而後該節點變成黑色。若是不是一顆空樹,插入元素分兩種狀況:向2-節點插入新元素和向3-節點插入新元素。

向2-節點插入新元素有兩種狀況

向2-節點插入新元素很簡單,若是新元素小於父節點的元素,直接插入紅色的節點便可;若是新元素大於父節點的元素,則產生一個紅色右連接,插完以後進行向上變換,在向上變換的過程當中(修復紅黑樹的性質)須要進行左旋轉,將右連接變成左連接,知足左傾紅黑樹的性質。

file

向3-節點插入新元素有三種狀況

1.新元素小於3-節點最小值

2.新元素位於3-節點最小值和最大值之間

3.新元素大於3-節點最大值

file

插入元素只有向上變換的過程,目的是爲了知足紅黑性質。

動畫:插入節點

算法動畫地址:B站

Code:插入元素

file

刪除元素

刪除元素既有向下變換也有向上變換:向下變換是爲了樹底下有一個被紅連接指向的節點能夠被刪除,不影響黑色平衡;向上變換是爲了修復基於2-3樹的左傾紅黑樹。

Code:向上變換(修復調整)

file

刪除元素有4個原則:

1.刪除元素的當前節點不能是2-節點;

2.向下變換不爲2-節點;

3.從樹底部刪除節點;

4.向上變換,消除右傾和4-節點。

刪除元素藉鑑了以前學的二分搜索樹刪除元素的思想,二分搜索樹刪除元素分爲刪除最小元素、刪除最大元素和刪除任意元素三種狀況:刪除最小元素是一直遞歸它的左孩子,直到左孩子爲空才進行刪除;刪除最大的元素則相反;若是是刪除任意的元素須要進行命中查找,找到了就取右子樹的最小值替換掉待刪除元素,而後進行右子樹的刪除最小元素。

紅黑樹刪除元素也是同樣的,不過是多了向下變換和向上變換的過程。由於是左傾紅黑樹,刪除最小元素是最合適的。

刪除最小元素

「算法4」裏的紅黑樹介紹了刪除最小鍵這一小節,雖沒有很詳細地介紹,但給出了沿着左連接向下變換的三種狀況:

1.若是當前節點(父節點位置)的左子節點不是2-節點,完成;

2.若是當前節點(父節點位置)的左子節點是2-節點而左子節點的兄弟節點不是2-節點,則左子節點借它的兄弟節點的一個鍵過來;

3.若是當前節點(父節點位置)的左子節點和左子節點的兄弟節點都是2-節點,將左子節點、當前節點和左子節點的兄弟節點合併成一個臨時的4-節點,使當前節點由3-節點變成2-節點或則4-節點變成3-節點。

file

Code:moveRedLeft

file

刪除最大節點思路也是同樣的,不過這是左傾紅黑樹,對刪除最大節點益處不大,甚至向下轉換的時候左傾調整爲右傾,向上轉換balance還要將右傾調整爲左傾。

動畫:刪除最小元素

算法動畫地址:B站

Code:刪除最小元素

file

刪除任意元素

在前面學習了刪除最小節點,刪除任意節點天然就很簡單了。咱們若是要刪除一個節點,首先進行命中查找,查找到這個待刪除元素,將右子樹的最小值替換掉這個待刪除元素,指向待刪除節點的連接顏色不能被改變。而後進行右子樹的刪除最小元素。

在命中查找過程當中,須要沿着左連接或沿着右連接進行向下轉換。前面刪除最小元素就是沿着左連接向下轉換的。

沿着右連接向下轉換也分三種狀況:

1.若是當前節點(父節點位置)的右子節點不是2-節點,將左傾轉換成右傾;

2.若是當前節點(父節點位置)的右子節點是2-節點而右子節點的兄弟節點不是2-節點,則右子節點借它的兄弟節點的一個鍵過來;

3.若是當前節點(父節點位置)的右子節點和右子節點的兄弟節點都是2-節點,將右子節點、當前節點和右子節點的兄弟節點合併成一個臨時的4-節點,使當前節點由3-節點變成2-節點或則4-節點變成3-節點。

file

Code:moveRedRight

file

Code:刪除任意元素

file

動畫:刪除任意元素

算法動畫地址:B站

閱讀原文可查看算法4裏的RedBlackTree.java源碼

點擊源碼

喜歡本文的朋友,歡迎關注公衆號「算法無遺策」,收看更多精彩內容

相關文章
相關標籤/搜索