紅黑樹是一種自平衡二叉查詢樹，是在計算機科學中用到的一種資料結構，典型用途是實現關聯陣列。它在 1972 年由魯道夫貝爾發明，被稱為「對稱二叉 B 樹」，它現代的名字源於利奧尼達斯J吉巴斯和羅伯特塞奇威克於 1978 年寫的一篇論文。紅黑樹的結構複雜，但它的操作有著良好的最壞情況執行時間，並且在實踐中高效：它可以在 text Olog n 時間內完成查詢、插入和刪除，這裡的 n 是樹中元素的數目。 歷史 1972 年，魯道夫拜爾發明瞭一種資料結構，那是一個 B 樹的四階特殊情況。此結構會維持所有從根到樹葉的路徑都具有相同數量的節點，創造了一個完美的平衡樹。然而，他們並不是二元搜尋樹。拜爾在他的論文中稱呼他們為「對稱二元 B 樹」（Symmetric binary Btree），後來他們以 234 樹或是 24 樹的形式開始流行。 在一篇 1972 年的論文〈A Dichromatic Framework for Balanced Trees〉中，利奧尼達斯J吉巴斯和羅伯特塞奇威克從對稱二元 B 樹 中推導出了紅黑樹。之所以選擇「紅色」是因為這是作者在帕羅奧多研究中心公司（Xerox PARC）工作時用彩色雷射列印機可以產生的最好看的顏色。另一種說法來自吉巴斯，是因為他們當時能用來繪製樹的筆有紅色和黑色。 用途和好處 紅黑樹和 AVL 樹一樣都對插入時間、刪除時間和查詢時間提供了最好可能的最壞情況擔保。這不只是使它們在時間敏感的應用，如即時應用中有價值，而且使它們有在提供最壞情況擔保的其他資料結構中作為基礎模板的價值；例如，在計算幾何中使用的很多資料結構都可以基於紅黑樹實現。 紅黑樹在函數語言程式設計中也特別有用，在這裡它們是最常用的持久資料結構之一，它們用來構造關聯陣列和集合，每次插入、刪除之後它們能保持為以前的版本。除了 text Olog n 的時間之外，紅黑樹的持久版本對每次插入或刪除需要 text Olog n 的空間。 紅黑樹是 234 樹的一種等同。換句話說，對於每個 234 樹，都存在至少一個數據元素是同樣次序的紅黑樹。在 234 樹上的插入和刪除操作也等同於在紅黑樹中顏色翻轉和旋轉。這使得 234 樹成為理解紅黑樹背後的邏輯的重要工具，這也是很多介紹演算法的教科書在紅黑樹之前介紹 234 樹的原因，儘管 234 樹在實踐中不經常使用。 紅黑樹相對於 AVL 樹來說，犧牲了部分平衡性以換取插入和刪除操作時少量的旋轉操作，整體來說效能要優於 AVL 樹。 性質 紅黑樹是每個節點都帶有顏色屬性的二叉查詢樹，顏色為紅色或黑色。在二叉查詢樹強制一般要求以外，對於任何有效的紅黑樹我們增加了如下的額外要求： 節點是紅色或黑色。 根是黑色。 所有葉子都是黑色（葉子是 NIL 節點）。 每個紅色節點必須有兩個黑色的子節點。（或者說從每個葉子到根的所有路徑上不能有兩個連續的紅色節點。）（或者說不存在兩個相鄰的紅色節點，相鄰指兩個節點是父子關係。）（或者說紅色節點的父節點和子節點均是黑色的。） 從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點。 下面是一個具體的紅黑樹的圖例： 這些約束確保了紅黑樹的關鍵特性：從根到葉子的最長的可能路徑不多於最短的可能路徑的兩倍長。結果是這個樹大致上是平衡的。因為操作比如插入、刪除和查詢某個值的最壞情況時間都要求與樹的高度成比例，這個在高度上的理論上限允許紅黑樹在最壞情況下都是高效的，而不同於普通的二叉查詢樹。 要知道為什麼這些性質確保了這個結果，注意到性質 4 導致了路徑不能有兩個毗連的紅色節點就足夠了。最短的可能路徑都是黑色節點，最長的可能路徑有交替的紅色和黑色節點。因為根據性質 5 所有最長的路徑都有相同數目的黑色節點，這就表明了沒有路徑能多於任何其他路徑的兩倍長。 在很多樹資料結構的表示中，一個節點有可能只有一個子節點，而葉子節點包含資料。用這種範例表示紅黑樹是可能的，但是這會改變一些性質並使演算法複雜。為此，本文中我們使用「nil 葉子」，如上圖所示，它不包含資料而只充當樹在此結束的指示。這些節點在繪圖中經常被省略，導致了這些樹好像同上述原則相矛盾，而實際上不是這樣。與此有關的結論是所有節點都有兩個子節點，儘管其中的一個或兩個可能是空葉子。 操作 因為每一個紅黑樹也是一個特化的二叉查詢樹，因此紅黑樹上的只讀操作與普通二叉查詢樹上的只讀操作相同。然而，在紅黑樹上進行插入操作和刪除操作會導致不再符合紅黑樹的性質。恢復紅黑樹的性質需要少量（text Olog n）的顏色變更（實際是非常快速的）和不超過三次樹旋轉（對於插入操作是兩次）。雖然插入和刪除很複雜，但操作時間仍可以保持為 text Olog n 次。 插入 我們首先以二叉查詢樹的方法增加節點並標記它為紅色。（如果設為黑色，就會導致根到葉子的路徑上有一條路上，多一個額外的黑節點，這個是很難調整的。但是設為紅色節點後，可能會導致出現兩個連續紅色節點的衝突，那麼可以透過顏色調換（color flips）和樹旋轉來調整。）下面要進行什麼操作取決於其他臨近節點的顏色。同人類的家族樹中一樣，我們將使用術語叔父節點來指一個節點的父節點的兄弟節點。注意： 性質 1 和性質 3 總是保持著。 性質 4 只在增加紅色節點、重繪黑色節點為紅色，或做旋轉時受到威脅。 性質 5 只在增加黑色節點、重繪紅色節點為黑色，或做旋轉時受到威脅。 在下面的示意圖中，將要插入的節點標為 N，N 的父節點標為 P，N 的祖父節點標為 G，N 的叔父節點標為 U。在圖中展示的任何顏色要麼是由它所處情形這些所作的假定，要麼是假定所暗含（imply）的。 對於每一種情形，我們將使用 C 示例程式碼來展示。透過下列函式，可以找到一個節點的叔父和祖父節點： node grandparent node nreturn nparentparent node uncle node nif nparent grandparent nleft return grandparent nright else return grandparent nleft 情形 1 新節點 N 位於樹的根上，沒有父節點。在這種情形下，我們把它重繪為黑色以滿足性質 2。因為它在每個路徑上對黑節點數目增加一，性質 5 符合。 void insert_case1 node nif nparent NULL ncolor BLACK else insert_case2 n 情形 2 新節點的父節點 P 是黑色，所以性質 4 沒有失效（新節點是紅色的）。在這種情形下，樹仍是有效的。性質 5 也未受到威脅，儘管新節點 N 有兩個黑色葉子子節點；但由於新節點 N 是紅色，透過它的每個子節點的路徑就都有同透過它所取代的黑色的葉子的路徑同樣數目的黑色節點，所以依然滿足這個性質。 void insert_case2 node nif nparentcolor BLACK return 樹仍舊有效 else insert_case3 n 注意：在下列情形下我們假定新節點的父節點為紅色，所以它有祖父節點；因為如果父節點是根節點，那父節點就應當是黑色。所以新節點總有一個叔父節點，儘管在情形 4 和 5 下它可能是葉子節點。 情形 3 如果父節點 P 和叔父節點 U 二者都是紅色，（此時新插入節點 N 做為 P 的左子節點或右子節點都屬於情形 3，這裡右圖僅顯示 N 做為 P 左子的情形）則我們可以將它們兩個重繪為黑色並重繪祖父節點 G 為紅色（用來保持性質 5）。現在我們的新節點 N 有了一個黑色的父節點 P。因為透過父節點 P 或叔父節點 U 的任何路徑都必定透過祖父節點 G，在這些路徑上的黑節點數目沒有改變。但是，紅色的祖父節點 G 可能是根節點，這就違反了性質 2，也有可能祖父節點 G 的父節點是紅色的，這就違反了性質 4。為了解決這個問題，我們在祖父節點 G 上遞迴地進行插入的整個過程。（把 G 當成是新加入的節點進行各種情形的檢查） void insert_case3 node nif uncle n NULL uncle ncolor RED nparentcolor BLACK uncle ncolor BLACK grandparent ncolor RED insert_case1 grandparent n else insert_case4 n 注意：在餘下的情形下，我們假定父節點 P 是其祖父 G 的左子節點。如果它是右子節點，情形 4 和情形 5 中的左和右應當對調。 情形 4 父節點 P 是紅色而叔父節點 U 是黑色或缺少，並且新節點 N 是其父節點 P 的右子節點而父節點 P 又是其父節點的左子節點。在這種情形下，我們進行一次左旋轉調換新節點和其父節點的角色；接著，我們按情形 5 處理以前的父節點 P 以解決仍然失效的性質 4。注意這個改變會導致某些路徑透過它們以前不透過的新節點 N（比如圖中 1 號葉子節點）或不透過節點 P（比如圖中 3 號葉子節點），但由於這兩個節點都是紅色的，所以性質 5 仍有效。 void insert_case4 node nif n nparentright nparent grandparent nleft rotate_left n n nleft else if n nparentleft nparent grandparent nright rotate_right n n nright insert_case5 n 情形 5：父節點 P 是紅色而叔父節點 U 是黑色或缺少，新節點 N 是其父節點的左子節點，而父節點 P 又是其父節點 G 的左子節點。在這種情形下，我們進行針對祖父節點 G 的一次右旋轉；在旋轉產生的樹中，以前的父節點 P 現在是新節點 N 和以前的祖父節點 G 的父節點。我們知道以前的祖父節點 G 是黑色，否則父節點 P 就不可能是紅色（如果 P 和 G 都是紅色就違反了性質 4，所以 G 必須是黑色）。我們切換以前的父節點 P 和祖父節點 G 的顏色，結果的樹滿足性質 4。性質 5 也仍然保持滿足，因為透過這三個節點中任何一個的所有路徑以前都透過祖父節點 G，現在它們都透過以前的父節點 P。在各自的情形下，這都是三個節點中唯一的黑色節點。 void insert_case5 node nnparentcolor BLACK grandparent ncolor RED if n nparentleft nparent grandparent nleft rotate_right nparent else Here n nparentright nparent grandparent nright rotate_left nparent 注意插入實際上是原地演算法，因為上述所有呼叫都使用了尾部遞迴。 刪除 如果需要刪除的節點有兩個兒子，那麼問題可以被轉化成刪除另一個只有一個兒子的節點的問題（為了表述方便，這裡所指的兒子，為非葉子節點的兒子）。對於二叉查詢樹，在刪除帶有兩個非葉子兒子的節點的時候，我們要麼找到它左子樹中的最大元素、要麼找到它右子樹中的最小元素，並把它的值轉移到要刪除的節點中（如在這裡所展示的那樣）。我們接著刪除我們從中複製出值的那個節點，它必定有少於兩個非葉子的兒子。因為只是複製了一個值（沒有複製顏色），不違反任何性質，這就把問題簡化為如何刪除最多有一個兒子的節點的問題。它不關心這個節點是最初要刪除的節點還是我們從中複製出值的那個節點。 在本文餘下的部分中，我們只需要討論刪除只有一個兒子的節點（如果它兩個兒子都為空，即均為葉子，我們任意將其中一個看作它的兒子）。如果我們刪除一個紅色節點（此時該節點的兒子將都為葉子節點），它的父親和兒子一定是黑色的。所以我們可以簡單的用它的黑色兒子替換它，並不會破壞性質 3 和性質 4。透過被刪除節點的所有路徑只是少了一個紅色節點，這樣可以繼續保證性質 5。另一種簡單情況是在被刪除節點是黑色而它的兒子是紅色的時候。如果只是去除這個黑色節點，用它的紅色兒子頂替上來的話，會破壞性質 5，但是如果我們重繪它的兒子為黑色，則曾經透過它的所有路徑將透過它的黑色兒子，這樣可以繼續保持性質 5。 需要進一步討論的是在要刪除的節點和它的兒子二者都是黑色的時候，這是一種複雜的情況（這種情況下該節點的兩個兒子都是葉子節點，否則若其中一個兒子是黑色非葉子節點，另一個兒子是葉子節點，那麼從該節點透過非葉子節點兒子的路徑上的黑色節點數最小為 2，而從該節點到另一個葉子節點兒子的路徑上的黑色節點數為 1，違反了性質 5）。我們首先把要刪除的節點替換為它的兒子。出於方便，稱呼這個兒子為 N（在新的位置上），稱呼它的兄弟（它父親的另一個兒子）為 S。在下面的示意圖中，我們還是使用 P 稱呼 N 的父親，SL 稱呼 S 的左兒子，SR 稱呼 S 的右兒子。我們將使用下述函式找到兄弟節點： struct node sibling struct node n if n nparentleft return nparentright else return nparentleft 我們可以使用下列程式碼進行上述的概要步驟，這裡的函式 replace_node 替換 child 到 n 在樹中的位置。出於方便，在本章節中的程式碼將假定空葉子被用不是 NULL 的實際節點物件來表示（在插入章節中的程式碼可以同任何一種表示一起工作）。 void delete_one_child struct node n Precondition n has at most one nonnull child struct node child is_leaf nright nleft nright replace_node n child if ncolor BLACKif childcolor RED childcolor BLACK else delete_case1 child free n 如果 N 和它初始的父親是黑色，則刪除它的父親導致透過 N 的路徑都比不透過它的路徑少了一個黑色節點。因為這違反了性質 5，樹需要被重新平衡。有幾種情形需要考慮： 情形 1 N 是新的根。在這種情形下，我們就做完了。我們從所有路徑去除了一個黑色節點，而新根是黑色的，所以性質都保持著。 void delete_case1 struct node n if nparent NULL delete_case2 n 注意：在情形 2、5 和 6 下，我們假定 N 是它父親的左兒子。如果它是右兒子，則在這些情形下的左和右應當對調。 情形 2： S 是紅色。在這種情形下我們在 N 的父親上做左旋轉，把紅色兄弟轉換成 N 的祖父，我們接著對調 N 的父親和祖父的顏色。完成這兩個操作後，儘管所有路徑上黑色節點的數目沒有改變，但現在 N 有了一個黑色的兄弟和一個紅色的父親（N 的新兄弟必是黑色，因為新兄弟先前是紅色 S 的一個兒子），所以我們可以接下去按情形 4、情形 5 或情形 6 來處理。 （注意：這裡的圖中沒有顯示出來，N 是刪除了黑色節點後替換上來的子節點，所以這個過程中由 PXN 變成了 PN，實際上是少了一個黑色節點，也可以理解為 Parent Black 和 Silbing Red 那麼他們的孩子黑色節點的數目肯定不等，讓他們做新兄弟肯定是不平衡的，還需後面繼續處理。這裡看英文版本的 比較的明瞭） void delete_case2 struct node n struct node s sibling n if scolor REDnparentcolor RED scolor BLACK if n nparentleft rotate_left nparent else rotate_right nparent delete_case3 n 情形 3： N 的父親、S 和 S 的兒子都是黑色的。在這種情形下，我們簡單的重繪 S 為紅色。結果是透過 S 的所有路徑，它們就是以前不透過 N 的那些路徑，都少了一個黑色節點。因為刪除 N 的初始的父親使透過 N 的所有路徑少了一個黑色節點，這使事情都平衡了起來。但是，透過 P 的所有路徑現在比不透過 P 的路徑少了一個黑色節點，所以仍然違反性質 5。要修正這個問題，我們要從情形 1 開始，在 P 上做重新平衡處理。 void delete_case3 struct node n struct node s sibling n if nparentcolor BLACK scolor BLACK sleftcolor BLACK srightcolor BLACK scolor RED delete_case1 nparent else delete_case4 n 情形 4： S 和 S 的兒子都是黑色，但是 N 的父親是紅色。在這種情形下，我們簡單的交換 N 的兄弟和父親的顏色。這不影響不透過 N 的路徑的黑色節點的數目，但是它在透過 N 的路徑上對黑色節點數目增加了一，添補了在這些路徑上刪除的黑色節點。 void delete_case4 struct node n struct node s sibling n if（nparentcolor RED scolor BLACK sleftcolor BLACK srightcolor BLACK scolor RED nparentcolor BLACK else delete_case5 n 情形 5： S 是黑色，S 的左兒子是紅色，S 的右兒子是黑色，而 N 是它父親的左兒子。在這種情形下我們在 S 上做右旋轉，這樣 S 的左兒子成為 S 的父親和 N 的新兄弟。我們接著交換 S 和它的新父親的顏色。所有路徑仍有同樣數目的黑色節點，但是現在 N 有了一個黑色兄弟，他的右兒子是紅色的，所以我們進入了情形 6。N 和它的父親都不受這個變換的影響。 void delete_case5 struct node n struct node s sibling n if（scolor BLACK this if statement is trivial due to Case 2 even though Case two changed the sibling to a siblings child the siblings child cant be red since no red parent can have a red child the following statements just force the red to be on the left of the left of the parent or right of the right so case six will rotate correctly if n nparentleft srightcolor BLACK sleftcolor RED this last test is trivial too due to cases 24 scolor RED sleftcolor BLACK rotate_right s else if n nparentright sleftcolor BLACK srightcolor RED this last test is trivial too due to cases 24 scolor RED srightcolor BLACK rotate_left s delete_case6 n 情形 6： S 是黑色，S 的右兒子是紅色，而 N 是它父親的左兒子。在這種情形下我們在 N 的父親上做左旋轉，這樣 S 成為 N 的父親（P）和 S 的右兒子的父親。我們接著交換 N 的父親和 S 的顏色，並使 S 的右兒子為黑色。子樹在它的根上的仍是同樣的顏色，所以性質 3 沒有被違反。但是，N 現在增加了一個黑色祖先：要麼 N 的父親變成黑色，要麼它是黑色而 S 被增加為一個黑色祖父。所以，透過 N 的路徑都增加了一個黑色節點。 此時，如果一個路徑不透過 N，則有兩種可能性： 它透過 N 的新兄弟。那麼它以前和現在都必定透過 S 和 N 的父親，而它們只是交換了顏色。所以路徑保持了同樣數目的黑色節點。 它透過 N 的新叔父，S 的右兒子。那麼它以前透過 S、S 的父親和 S 的右兒子，但是現在只通過 S，它被假定為它以前的父親的顏色，和 S 的右兒子，它被從紅色改變為黑色。合成效果是這個路徑通過了同樣數目的黑色節點。 在任何情況下，在這些路徑上的黑色節點數目都沒有改變。所以我們恢復了性質 4。在示意圖中的白色節點可以是紅色或黑色，但是在變換前後都必須指定相同的顏色。 void delete_case6 struct node n struct node s sibling n scolor nparentcolor nparentcolor BLACK if n nparentleftsrightcolor BLACK rotate_left nparent else sleftcolor BLACK rotate_right nparent 同樣的，函式呼叫都使用了尾部遞迴，所以演算法是原地演算法。此外，在旋轉之後不再做遞迴呼叫，所以進行了恆定數目（最多 3 次）的旋轉。 C 示例程式碼 define NIL NULL define BLACK 1 define RED 0 include iostream using namespace std class bst private struct Node int value bool color Node leftTree rightTree parent Node value 0 color RED leftTree NULL rightTree NULL parent NULL Node grandparent if parent NULLreturn NULL return parentparent Node uncle if grandparent NULL return NULL if parent grandparent rightTree return grandparent leftTree else return grandparent rightTree Node sibling if parentleftTree this return parentrightTree else return parentleftTree void rotate_right Node pNode gp pgrandparent Node fa pparent Node y prightTree faleftTree y if y NIL yparent fa prightTree fa faparent p if root fa root p pparent gp if gp NULLif gpleftTree fa gpleftTree p else gprightTree p void rotate_left Node pif pparent NULL root p return Node gp pgrandparent Node fa pparent Node y pleftTree farightTree y if y NIL yparent fa pleftTree fa faparent p if root fa root p pparent gp if gp NULLif gpleftTree fa gpleftTree p else gprightTree p void inorder Node pif p NIL return if pleftTree inorder pleftTree cout pvalue if prightTree inorder prightTree string outputColor bool color return color BLACK RED Node getSmallestChild Node pif pleftTree NIL return p return getSmallestChild pleftTree bool delete_child Node p int dataif pvalue dataif pleftTree NILreturn false return delete_child pleftTree data else if pvalue dataif prightTree NILreturn false return delete_child prightTree data else if pvalue dataif prightTree NILdelete_one_child p return true Node smallest getSmallestChild prightTree swap pvalue smallestvalue delete_one_child smallest return true else return false void delete_one_child Node pNode child pleftTree NIL prightTree pleftTree if pparent NULL pleftTree NIL prightTree NIL p NULL root p return if pparent NULL delete p childparent NULL root child rootcolor BLACK return if pparentleftTree ppparentleftTree child else pparentrightTree child childparent pparent if pcolor BLACKif childcolor REDchildcolor BLACK else delete_case child delete p void delete_case Node pif pparent NULLpcolor BLACK return if psibling color RED pparentcolor RED psibling color BLACK if p pparentleftTree rotate_left psibling rotate_left pparent else rotate_right psibling rotate_right pparent if pparentcolor BLACK psibling color BLACK psibling leftTreecolor BLACK psibling rightTreecolor BLACK psibling color RED delete_case pparent else if pparentcolor RED psibling color BLACK psibling leftTreecolor BLACK psibling rightTreecolor BLACK psibling color RED pparentcolor BLACK else if psibling color BLACK if p pparentleftTree psibling leftTreecolor RED psibling rightTreecolor BLACK psibling color RED psibling leftTreecolor BLACK rotate_right psibling leftTree else if p pparentrightTree psibling leftTreecolor BLACK psibling rightTreecolor RED psibling color RED psibling rightTreecolor BLACK rotate_left psibling rightTree psibling color pparentcolor pparentcolor BLACK if p pparentleftTreepsibling rightTreecolor BLACK rotate_left psibling else psibling leftTreecolor BLACK rotate_right psibling void insert Node p int dataif pvalue dataif pleftTree NIL insert pleftTree data else Node tmp new Node tmpvalue data tmpleftTree tmprightTree NIL tmpparent p pleftTree tmp insert_case tmp else if prightTree NIL insert prightTree data else Node tmp new Node tmpvalue data tmpleftTree tmprightTree NIL tmpparent p prightTree tmp insert_case tmp void insert_case Node pif pparent NULL root p pcolor BLACK return if pparentcolor REDif puncle color RED pparentcolor puncle color BLACK pgrandparent color RED insert_case pgrandparent else if pparentrightTree p pgrandparent leftTree pparent rotate_left p pcolor BLACK pparentcolor RED rotate_right p else if pparentleftTree p pgrandparent rightTree pparent rotate_right p pcolor BLACK pparentcolor RED rotate_left p else if pparentleftTree p pgrandparent leftTree pparent pparentcolor BLACK pgrandparent color RED rotate_right pparent else if pparentrightTree p pgrandparent rightTree pparent pparentcolor BLACK pgrandparent color RED rotate_left pparent void DeleteTree Node pif p p NILreturn DeleteTree pleftTree DeleteTree prightTree delete p public bst NIL new Node NILcolor BLACK root NULL bst if root DeleteTree root delete NIL void inorder if root NULL return inorder root cout endl void insert int x if root NULLroot new Node rootcolor BLACK rootleftTree rootrightTree NIL rootvalue x else insert root x bool delete_value int data return delete_child root data private Node root NIL 漸近邊界的證明 包含 n 個內部節點的紅黑樹的高度是 text Olog n。 定義： h v 表示以節點 v 為根的子樹的高度。 bh v 表示從 v 到子樹中任何葉子的黑色節點的數目（如果 v 是黑色則不計數它，也叫做黑色高度）。 引理：以節點 v 為根的子樹有至少 2bh v1 個內部節點。 引理的證明（透過歸納高度）： 基礎：h v 0 如果 v 的高度是零則它必定是 NIL，因此 bh v0。所以： 2bh v1 201 11 0 歸納假設：h vk 的 v 有 2bh v11 個內部節點暗示了 h v k1 的 v 有 2bh v1 個內部節點。 因為 v 有 h v 0 所以它是個內部節點。同樣的它有黑色高度要麼是 bh v 要麼是 bh v1（依據 v 是紅色還是黑色）的兩個兒子。透過歸納假設每個兒子都有至少 2bh v11 個內部接點，所以 v 有： 2bh v11 2bh v11 1 2bh v1 個內部節點。 使用這個引理我們現在可以展示出樹的高度是對數性的。因為在從根到葉子的任何路徑上至少有一半的節點是黑色（根據紅黑樹性質 4），根的黑色高度至少是 frac h root2。透過引理我們得到： n geqslant 2frac h root2 1 leftrightarrow log n1 geqslant frac h root2 leftrightarrow h root leqslant 2log n1 因此根的高度是 text Olog n。 參見 AVL 樹 B 樹 跳躍列表 一種有可能替代平衡樹的資料結構 伸展樹 234 樹 Treap 引用 Mathworld RedBlack Tree San Diego State University CS 660 RedBlack tree notes by Roger Whitney Cormen Leiserson Rivest Stein Introduction to Algorithms Massachusetts The MIT Press 2002 pp27377 ISBN 0070131511 外部連結 An applet quick explanation RedBlack Tree Demonstration An example（animated GIF 200KB） An example（static picture） Another explanation（pictures source code and Java interactive animation） RedBlack Tree Demonstration by David M Howard RBT A SmallEiffel RedBlack Tree Library libredblack A C RedBlack Tree Library Data Structures and Algorithm Analysis in C 2nd edition RedBlack Tree C Code RedBlack Trees by Thomas Niemann 紅黑樹的介紹和實現 H Category 樹結構 CategoryB 樹 Category 二叉樹 Category 搜尋樹