我們想,一棵二叉樹怎么就是最壞情況,那就是它退化為一個鏈表,這樣查找就成了遍歷。問題是,平衡二叉樹怎么會退回鏈表!它是怎么保持平衡的?能不能簡單地闡述?當然能夠。一般的講述紅黑樹的資料都是直接給出黑節點同樣。紅節點不連續等來作為一個足夠硬可是又不是太硬的約束來保證樹的平衡,但其實,它還有更加簡單的理解方式。
1.查找-在高度不在寬度
對於查找而言。假設一棵二叉樹的高度是N。那么最多能夠在N步內完畢查找,這個不用解釋,解釋這個有點喧賓奪主了。這就是說,樹的高度要盡可能矮。考慮到查找的平均情況。葉子節點到根節點的距離不能區別太大。2.二叉樹的不平衡根源
一棵樹在查找看來變得不平衡是由於子樹的高度相差非常大。二叉樹為什么會這么easy變得不平衡,非常easy,由於它僅僅有二叉,左右均有50%的概率,那么插入N個節點所有都是左節點或者右節點的概率就是50%的N次方。假設是8叉樹,那么這個概率就是12.5%的N次方。哪個概率大,自己算。
3.多叉樹-寬度換高度
在第1節以及第2節。我們已經知道,樹的寬度越大,高度越小,這樣查詢起來越快,Cisco路由器里不是有256叉乃至1024叉樹嗎?可是這樣真的非常好嗎?對於稀疏節點,這樣會嚴重消耗內存。假設我們考慮CPU的MMU系統,就會知道,二級頁表和三級頁表的區別就在於對付稀疏地址空間的效果不同。
4.權衡-2,3樹
我們發現,道生一。一生二。二叉樹是一個完美的開始,可是我們發現它特別easy傾斜,傾斜的時候別觸摸。我們也不能一下子就上256叉樹。即使那樣在海量節點情況下也抗不住。因此這樣的盲目寬度換高度的方案沒有可擴展性。我們須要找出一種動態的機制,讓一棵樹動態調整保持平衡。為了更加easy找出這個機制,讓它更加easy現形。臨時不斷添加樹的寬度。假設添加到3叉樹還找不到方案,就添加到4叉樹...我們說的N叉樹並非說一個節點一定有N個子節點。而是說它最多有N個子節點。
迄今為止。曾經都是我自己形而上的觀點,幾年前我的想法就到此為止,原因在於那段時間特別郁悶,就想找出些技術上的形而上思想。可是突然自己變好了。就沒有繼續下去。幸運的是。我如今發現確實有這么一個方案,而紅黑樹就是從3叉樹回退過去的。
讓我高興的是,我的思路並沒有跑偏。
5.2-3樹的平衡變換
假設是二叉樹。那么你插入一個節點。你僅僅有最多1次機會保持子樹的高度不變,假設是一個三叉樹,那么就有2次機會。如今開始,我們為二叉樹添了一叉。變成了三叉樹。二叉樹的時候。一個節點有兩個分支,三叉樹的時候,有三個分支。一個點能夠將區間分為兩個部分區域,要想將一個區間分為三個部分區域,就須要兩個點,因此三叉的情形下,節點存儲的是兩個點而不是一個。例如以下圖所看到的:
如今考慮插入一個新節點,這個2-3樹怎么保持平衡。非常easy,我們知道,插入的位置一定是葉子,假設當前的樹是平衡的,如今分兩種情況:
1).插入的新葉子節點的父節點是一個二叉節點
這樣的情況最簡單,二叉節點變三叉節點就可以,例如以下圖所看到的:
2).插入的新葉子節點的父節點是一個三叉節點
這樣的情況比較復雜。樹總是要長高的,保持平衡的方式就是同一時候長高,而這是不可能的,插入一個節點僅僅能讓該節點所在的子樹長高。然而,假設能將這個信息上升到根部,在根部長高。就實現了“同一時候長高”!
還是循着上面的那個思路。我們繼續添加樹叉的數量。我們把它添加到4。新節點的插入例如以下圖所看到的:
非常遺憾。沒有完畢任務,可是終於我們提出了兩個問題,僅僅要攻克了這兩個問題,所有問題就攻克了。
解決這兩個問題,無疑都要牽扯到節點P的父節點以及再往上的節點。有兩種可能:可能性1:P的父節點PP是一個二叉節點
這個太爽,我們直接把P以及它的子樹所有提到PP節點就可以,相似B插入的情景,例如以下圖所看到的:

問題2解決。
可能性2:P的父節點PP是一個三叉節點這就有點不好辦了,只是有最后一擊!
無論如何先把P節點以及其子節點所有上提到PP,保持最底部的平衡性。這樣就能夠遞歸攻克了,此時我們重新遇到了往一個三叉節點里面插入子節點的問題了。為了不添加樹高,唯一的方式就是膨脹成一個四叉節點-寬度換高度。例如以下圖所看到的:

最后。我們發現,在遞歸的過程中。要么碰到了P..P是個二叉節點。此時依照問題2的解決方案將當前節點的值直接提到P...P中,其子樹減少一個高度,抵消添加的高度。平衡保持。遞歸結束,要么遞歸到了根節點。此時僅僅須要一個分裂操作就可以完美結束!
6.演進到紅黑樹
非常顯然,通過上面的描寫敘述。我們似乎找到了一個使樹保持平衡的方案。並且是相當完美的平衡!核心就是寬度和高度之間的博弈。我們總是能夠用一個寬度抵消一層高度,整個過程就是一次或者多次的一加一減,終於的結果還是0!然而。這也不再是二叉樹了,有的節點變成了三叉,並且保存了兩個值。該兩個值將區間切割成了三部分,是為三叉!
因此在使用上就不如二叉樹方便,比較操作復雜化了。其實,將三叉節點處理成二叉節點,這棵樹就成了紅黑樹!怎么處理呢?非常easy。例如以下圖所看到的:

看到了吧,紅色節點就是從2-3樹中分出來的,為了維持一棵二叉樹而不是2-3樹。必須將三叉節點變成二叉節點,這是一個寬度換高度得回退。即高度換寬度。當然代價就是不再完美平衡。
依照以上的這個變換,你自己試試看,能夠變出兩個連續的紅節點嗎?NO!還在糾結紅黑樹的性質概念嗎?看了它的演進,你會發現,非常多紅黑樹的復雜概念和讓人沒有頭緒的性能都是自然而然的。以下我們來看一下它的最壞情況是什么。
還是以2-3樹分析,假設在一棵2-3樹中,最左邊路徑上的節點所有是三叉節點。而最右邊路徑上的節點都是二叉節點,那么把它變換成二叉紅黑樹之后,就會發現最左邊的路徑上是紅黑間隔的節點。而最右邊的路徑上所有是黑節點,它們的高度差接近2倍。出現這樣的情況是令人悲哀的。可是也是極低概率的。
紅黑樹的所有包含旋轉等操作。都能夠映射到2-3樹中,而我們對2-3樹以及高度和寬度之間的博弈已經足夠理解了。
請再次去理解紅黑樹吧,再看看它的性質和概念,together with左旋和右旋。是不是有一種新的體會呢?
