1. 程式人生 > >seaboat的專欄——a free boat on the sea.

seaboat的專欄——a free boat on the sea.

前言

推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。

紅黑樹

紅黑(Red-black)樹是一種自平衡二叉查詢樹,1972年由Rudolf Bayer發明,它與AVL樹類似,都在插入和刪除操作時能通過旋轉操作保持二叉查詢樹的平衡,以便能獲得高效的查詢效能。

它可以在 ${\text{O}}(\log n)$時間內做查詢,插入和刪除等操作。紅黑樹是2-3-4樹的一種等同,但有些紅黑樹設定只能左邊是紅樹,這種情況就是2-3樹的一種等同了。

對於AVL樹來說,紅黑樹犧牲了部分平衡性以換取插入/刪除操作時少量的旋轉操作,整體來說效能要優於AVL樹。

紅黑樹性質

  • 節點是紅色或黑色。
  • 根節點是黑色。
  • 每個葉節點(NIL節點)是黑色的。
  • 每個紅色節點的兩個子節點都為黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
  • 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

image

紅黑樹的性質也就是說樹有自己特殊的規定,有了這些約束就能保證從根節點到葉子節點的最長路徑不多於最短路徑的兩倍(因為每個葉子到根都不能有兩個連續的紅色節點,且任一節點到每個葉子包含相同數目的黑色節點)。於是就能保證該樹大致上平衡,保證了查詢的效率。

旋轉和變色

紅黑樹因為是二叉查詢樹,所以在樹上做查詢和普通的二叉查詢樹相同。但對於插入和刪除操作可能會導致樹不符合紅黑樹性質,因此需要做少量(${\text{O}}(\log n)$

)的變色和不超過三次的旋轉操作(對於插入最多兩次)。

插入操作

插入“A”,此時為根節點,標為黑色,另外存在兩個NIL葉子節點,

image

插入“L”,“L”與“A”比較,

image

“L”大於“A”,於是成為“A”節點的右子節點,“L”下有兩個NIL葉子節點,此時沒有破壞紅黑樹性質,不用進行額外操作,完成“L”的插入。

image

插入“O”,“O”與“A”比較,

image

“O”大於“A”,往右,繼續與“L”比較,

image

“O”大於“L”,於是成為“L”節點的右子節點,

image

此時發現“O”節點和其父節點“L”都是紅色的,已經破壞了紅黑樹的性質了,另外“O”節點為右子節點,“L”也是一個右子節點,所以應該進行左單旋操作,

左單旋操作主要是將“L”節點提升,原來的父節點“A”變為它的左子節點,“L”節點原來的左子節點變成“A”節點的右子節點。

image

此時還需要將原來“O”節點的父節點“L”與祖父節點“A”之間的顏色進行對調,才能符合紅黑樹的性質,完成“O”的插入。

image

插入“M”,“M”與“L”比較,

image

“M”大於“L”,往右,繼續與“O”比較,

image

“M”小於“O”,於是成為“O”節點的左子節點,

image

此時發現“M”節點和其父節點“O”都是紅色的,已經破壞了紅黑樹的性質了,另外因為“D”節點為右子節點,“M”為左子節點,且其父節點“O”與其叔父節點“A”都為紅色,所以先將父節點和叔父節點的顏色變為黑色,然後祖父節點顏色變為紅色,

image

但是現在還有一個性質沒滿足,即根不能為紅色,所以將根節點“L”再設為黑色,完成“M”的插入。

image

插入“H”,“H”與“L”比較,

image

“H”小於“L”,往左,繼續與“A”比較,

image

“H”大於“A”,於是成為“A”節點的右子節點,沒有破壞紅黑樹性質,完成“H”插入。

image

繼續插入“E”,最終將成為“H”節點的左子節點,此時“E”節點和“H”節點都為紅色,破壞了紅黑樹性質。

image

因為“E”為左子節點,其父節點為右子節點,所以執行右單旋操作。右單旋主要是將“E”節點提升,原來的父節點“H”變為它的右子節點,“E”節點原來的右子節點變成“H”節點的左子節點。

image

右單旋後發現“E”和“H”都為紅色,此時“H”為右子節點,“E”也為右子節點,繼續進行左單旋操作。將“E”提升,“A”作為“E”的左子節點,“E”原來左子節點變為“A”的右子節點。

image

此外還需要將原來“H”節點的父節點“E”與祖父節點“A”之間的顏色進行對調,完成“E”的插入。

image

繼續插入“D”,最終將成為“A”節點的右子節點,此時“D”節點和“A”節點都為紅色,破壞了紅黑樹性質。

image

此時父節點“A”和叔父節點“H”都為紅色,所以先將父節點和叔父節點的顏色變為黑色,然後祖父節點顏色變為紅色,完成“D”的插入。

image

繼續插入“G”,結果如下。

image

我們繼續插入“F”,最終它成為“G”的左子節點,此時發現“F”節點和其父節點“G”都是紅色的,已經破壞了紅黑樹的性質了,另外因為“F”節點為左子節點,“G”也為左子節點,且其叔父節點為空節點,所以進行右單旋操作。

image

右單旋操作主要將“G”提升,“H”變為“G”的右子節點,“G”原來的右子節點變為“H”的左子節點。

image

此時還需要將原來“F”節點的父節點“G”與祖父節點“H”之間的顏色進行對調,才能符合紅黑樹的性質,完成“F”的插入。

image

查詢

假設要找“F”,從根節點開始,

image

“F”小於“L”,往左,

image

“F”大於“E”,往右,

image

“F”小於“G”,往左,找到。

image

-------------推薦閱讀------------

跟我交流,向我提問:

歡迎關注: