真正理解紅/黑樹狀結構,真正的(Linux核心裡大量用到的資料結構,且常被二貨問到)

來源:互聯網
上載者:User

標籤:

作為一種資料結構,紅/黑樹狀結構可謂不算樸素,因為各種宣傳讓它過於神秘,網上搜羅了一大堆的關於紅/黑樹狀結構的文章,不外乎千篇一律,介紹概念,分析效能,貼上代碼,然後給上罪惡的一句話,它最壞情況怎麼怎麼地...
      
       我們想,一棵二叉樹怎麼就是最壞情況,那就是它退化為一個鏈表,這樣尋找就成了遍曆。問題是,平衡二叉樹怎麼會退回鏈表!它是怎麼保持平衡的?能不能簡單地闡述?當然可以!一般的講述紅/黑樹狀結構的資料都是直接給出黑節點相同,紅節點不連續等來作為一個足夠硬但是又不是太硬的約束來保證樹的平衡,但事實上,它還有更加簡單的理解方式。

1.尋找-在高度不在寬度對於尋找而言,如果一棵二叉樹的高度是N,那麼最多可以在N步內完成尋找,這個不用解釋,解釋這個有點喧賓奪主了。這就是說,樹的高度要儘可能矮。考慮到尋找的平均情況,葉子節點到根節點的距離不能差別太大。

2.二叉樹的不平衡根源一棵樹在尋找看來變得不平衡是因為子樹的高度相差很大。
       二叉樹為什麼會這麼容易變得不平衡,很簡單,因為它只有二叉,左右均有50%的機率,那麼插入N個節點全部都是左節點或者右節點的機率就是50%的N次方,如果是8叉樹,那麼這個機率就是12.5%的N次方,哪個機率大,自己算。

3.多叉樹-寬度換高度在第1節以及第2節,我們已經知道,樹的寬度越大,高度越小,這樣查詢起來越快,Cisco路由器裡不是有256叉乃至1024叉樹嗎?但是這樣真的很好嗎?對於稀疏節點,這樣會嚴重消耗記憶體。
       如果我們考慮CPU的MMU系統,就會知道,二級頁表和三級頁表的區別就在於對付稀疏地址空間的效果不同。

4.權衡-2,3樹我們發現,道生一,一生二,二叉樹是一個完美的開始,但是我們發現它特別容易傾斜,傾斜的時候別觸摸。我們也不能一下子就上256叉樹,即使那樣在海量節點情況下也抗不住,因此這種盲目寬度換高度的方案沒有可擴充性。我們需要找出一種動態機制,讓一棵樹動態調整保持平衡。
       為了更加容易找出這個機制,讓它更加容易現形,暫時不斷增加樹的寬度,如果增加到3叉樹還找不到方案,就增加到4叉樹...我們說的N叉樹並不是說一個節點一定有N個子節點,而是說它最多有N個子節點。
       迄今為止,以前都是我自己形而上的觀點,幾年前我的想法就到此為止,原因在於那段時間特別鬱悶,就想找出些技術上的形而上思想,可是突然自己變好了,就沒有繼續下去。幸運的是,我現在發現確實有這麼一個方案,而紅/黑樹狀結構就是從3叉樹回退過去的。
       讓我高興的是,我的思路並沒有跑偏。
5.2-3樹的平衡變換如果是二叉樹,那麼你插入一個節點,你只有最多1次機會保持子樹的高度不變,如果是一個三叉樹,那麼就有2次機會。現在開始,我們為二叉樹添了一叉,變成了三叉樹。

       二叉樹的時候,一個節點有兩個分支,三叉樹的時候,有三個分支。一個點可以將區間分為兩個部分地區,要想將一個區間分為三個部分地區,就需要兩個點,因此三叉的情形下,節點儲存的是兩個點而不是一個,如所示:



現在考慮插入一個新節點,這個2-3樹怎麼保持平衡。非常簡單,我們知道,插入的位置一定是葉子,假設當前的樹是平衡的,現在分兩種情況:
1).插入的新葉子節點的父節點是一個二叉節點這種情況最簡單,二叉節點變三叉節點即可,如所示:



2).插入的新葉子節點的父節點是一個三叉節點 這種情況比較複雜。樹總是要長高的,保持平衡的方式就是同時間長度高,而這是不可能的,插入一個節點只能讓該節點所在的子樹長高。然而,如果能將這個資訊上升到根部,在根部長高,就實現了“同時間長度高”!
       還是循著上面的那個思路,我們繼續增加樹叉的數量,我們把它增加到4!新節點的插入如所示:



很遺憾,沒有完成任務,但是最終我們提出了兩個問題,只要解決了這兩個問題,所有問題就解決了。

       解決這兩個問題,無疑都要牽扯到節點P的父節點以及再往上的節點,有兩種可能:
可能性1:P的父節點PP是一個二叉節點
這個太爽,我們直接把P以及它的子樹全部提到PP節點即可,類似B插入的情景,如所示:



問題2解決。

可能性2:P的父節點PP是一個三叉節點
這就有點不好辦了,不過有最後一擊!不管怎樣先把P節點以及其子節點全部上提到PP,保持最底部的平衡性,這樣就可以遞迴解決了,此時我們又一次遇到了往一個三叉節點裡面插入子節點的問題了,為了不增加樹高,唯一的方式就是膨脹成一個四叉節點-寬度換高度。如所示:



最後,我們發現,在遞迴的過程中,要麼碰到了P..P是個二叉節點,此時按照問題2的解決方式將當前節點的值直接提到P...P中,其子樹降低一個高度,抵消增加的高度,平衡保持,遞迴結束,要麼遞迴到了根節點,此時只需要一個分裂操作即可完美結束!



6.演化到紅/黑樹狀結構很顯然,通過上面的描述,我們似乎找到了一個使樹保持平衡的方案,而且是相當完美的平衡!核心就是寬度和高度之間的博弈。我們總是可以用一個寬度抵消一層高度,整個過程就是一次或者多次的一加一減,最終的結果還是0!
       然而,這也不再是二叉樹了,有的節點變成了三叉,並且儲存了兩個值,該兩個值將區間分割成了三部分,是為三叉!因此在使用上就不如二叉樹方便,比較操作複雜化了。事實上,將三叉節點處理成二叉節點,這棵樹就成了紅/黑樹狀結構!怎麼處理呢?很簡單!如所示:



看到了吧,紅色節點就是從2-3樹中分出來的,為了維持一棵二叉樹而不是2-3樹,必須將三叉節點變成二叉節點,這是一個寬度換高度得回退,即高度換寬度,當然代價就是不再完美平衡。

       按照以上的這個變換,你自己試試看,可以變出兩個連續的紅節點嗎?NO!還在糾結紅/黑樹狀結構的性質概念嗎?看了它的演化,你會發現,很多紅/黑樹狀結構的複雜概念和讓人沒有頭緒的效能都是自然而然的。下面我們來看一下它的最壞情況是什麼。
       還是以2-3樹分析,如果在一棵2-3樹中,最左邊路徑上的節點全部是三叉節點,而最右邊路徑上的節點都是二叉節點,那麼把它變換成二叉紅/黑樹狀結構之後,就會發現最左邊的路徑上是紅黑間隔的節點,而最右邊的路徑上全部是黑節點,它們的高度差接近2倍。出現這樣的情況是令人悲哀的,但是也是極低機率的。
       紅/黑樹狀結構的所有包括旋轉等操作,都可以映射到2-3樹中,而我們對2-3樹以及高度和寬度之間的博弈已經足夠理解了。請再次去理解紅/黑樹狀結構吧,再看看它的性質和概念,together with左旋和右旋,是不是有一種新的體會呢?

真正理解紅/黑樹狀結構,真正的(Linux核心裡大量用到的資料結構,且常被二貨問到)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.