紅黑樹動圖解析

紅黑樹動圖解析

一、啥是紅黑樹?

紅黑樹(Red Black Tree) 是一種自平衡二叉查找樹,是在計算機科學中用到的一種數據結構,典型的用途是實現關聯數組。因此想要弄清楚紅黑樹,我們需要先解決幾個問題:

  • 二叉查找樹是什麼?
  • 爲什麼會出現紅黑樹?

二、剖析二叉查找樹

二叉查找樹特性

二叉查找樹(Binary Search Tree)是一顆二叉樹,簡稱BST。就像我們說int都是整數一樣,BST這一種二叉樹需要滿足如下三個特性:

  • 某節點的左子樹節點值僅包含小於該節點值
  • 某節點的右子樹節點值僅包含大於該節點值
  • 左右子樹每個也必須是二叉查找樹
長啥樣?

在線演示BST網址:https://www.cs.usfca.edu/~galles/visualization/BST.html

ps:這個網站不只二叉樹,絕大部分算法的增刪改查都可以去演示,是理解算法的好幫手,強烈建議保存!

BST在理想情況下是如下這樣的:

BST理想狀態

當BST發生傾斜後是這樣的:

發生傾斜的BST演示
在理想的情況下,二叉查找樹增刪查改的時間複雜度爲O(logN)(其中N爲節點數),最壞的情況下爲O(N)

怎麼解決傾斜

通過以上兩個相同數據的BST的演示,我們發現了一個問題,同樣的數據組成,只是因爲數據插入的先後順序,就使得產生的二叉查找樹發生了傾斜
那麼我們怎麼解決這個問題呢?首先想到的就是每次插入或者刪除數據的時候都進行判斷,對已經存在的樹結構進行旋轉,使其維持在logN的高度上,這樣不管我們按照什麼樣的順序插入數據,最終的結構只要能滿足logN的高度,那它的結構一定是理想狀態下的。

紅黑樹產生

基於BST存在的問題,一種新的樹——平衡二叉查找樹(Balanced BST)產生了。平衡樹在插入和刪除的時候,會通過旋轉操作將高度保持在logN。其中兩款具有代表性的平衡樹分別爲AVL樹和紅黑樹。AVL樹由於實現比較複雜,而且插入和刪除性能差,因此在實際環境中我們更多的是應用紅黑樹。

三、紅黑樹的用途及特性

用途

紅黑樹(Red-Black Tree)以下簡稱RBTree的實際應用非常廣泛,比如Linux內核中的完全公平調度器、高精度計時器、ext3文件系統等等,各種語言的函數庫如Java的TreeMap和TreeSet,C++ STL的map、multimap、multiset等,是函數式語言中最常用的持久數據結構之一。
由於在java8裏HashMap的底層實現用RBTree取代鏈表,使得性能得到了提升,因此很多人才去關注或者深入學習紅黑樹。

特性

RBT樹上的每個節點,都要遵循下面的規則:

  1. 每個節點都是紅色或者黑色;
  2. 根節點必須始終是黑色;
  3. 沒有兩個相鄰的紅色節點;
  4. 對每個結點,從該結點到其子孫節點的所有路徑上包含相同數目的黑結點。

RBT樹在理論上還是一棵BST樹,但是它在對BST的插入和刪除操作時會維持樹的平衡,即保證樹的高度在[logN,logN+1](理論上,極端的情況下可以出現RBTree的高度達到2*logN,但實際上很難遇到)。這樣RBTree的查找時間複雜度始終保持在O(logN)從而接近於理想的BST。RBTree的刪除和插入操作的時間複雜度也是O(logN)。RBT的查找操作就是BST的查找操作。
上面的規則看一下有個印象就好,接下來是紅黑樹比較複雜的地方,就是紅黑樹的調整,
爲了達到這一目的,

四、拒絕死記硬背,跟着動圖理解調整算法

爲了維持RBT的規則,RBT定義了兩個重要的操作:

  1. rotation:旋轉,這是樹達到平衡的關鍵;
  2. recolor :重新標記黑色或紅色。
4.1、 首先先看最基礎的recolor,也就是第一種情況

先看如下gif:
RBT recolor演示

小結一波:

通過上面動圖,我們發現整個插入及調整一共是如下7步:

  1. 新插入的節點004標記爲紅色;
  2. 插入後發現004的父節點005也是紅色,違反了RBT的規則3( 沒有兩個相鄰的紅色節點);
  3. 發現004的叔父節點007同樣是紅色;
  4. 使用recolor方法,把005和007也就是父節點和叔父節點標記爲黑色;
  5. 將004和它的祖父節點006標記爲相同的顏色,也就是紅色,往上遞歸重複步驟2,3;
  6. 發現它的祖父節點是根節點,標記爲黑色;
  7. 調整完畢。
4.2、開始考慮旋轉rotation方法,首先展示第二種情況:左旋

先看如下gif:
rotation之左旋

小結一波:

這裏我們就不用再分步驟去看了,只需要知道整體的調整方式就行了;左旋就是當新加入節點之後,樹的高度及顏色不再滿足RBT定義的規則後;將不滿足的節點進行左旋轉,使得它取代之前它的父節點,同時它的父節點變爲它的左子節點,最後應用第一種方法調整顏色的過程。

4.3、第三種情況:右旋

先看如下gif:
rotation之右旋

小結一波:

右旋就是以某節點爲中心進行向右的旋轉,取代併成爲之前自己的父節點,然後把之前的父節點變爲自己的右子節點,最後應用第一種方法調整顏色的過程。

五、總結

最後我們把實際使用中,或者研究HashMap源碼時需要提前瞭解的紅黑樹調整規則整理總結一下:
爲了方便記憶,我們取英文首字母,定義連續的三代節點,新增節點爲N,父節點爲P,叔父節點爲U,祖父節點爲G

情況 處理方式
N和U都是紅色 將P和U修改爲黑色,G修改爲紅色
N是P的左節點,同時U是黑色 對G進行一次右旋轉,然後根據規則調整顏色
N是P的右節點,同時U是黑色 首先對P進行一次左旋轉,然後套用上一種調整情況

紅黑樹看似複雜,其實只要我們理解了它的來源,定義的規則,爲了完成規則使用的方法及三種調整策略,然後多加練習,多觀察,就可以很容易的去掌握它的規律。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章