平衡樹——B樹、左偏紅黑樹和紅黑樹

最後我們來介紹B樹和其衍生出的(左偏)紅黑樹。
大部分的圖源自這個網站,你也可以在上面找到一些其他的數據結構。

1. B樹

我們發現二叉樹做不到絕對平衡。於是我們考慮多叉樹。
B 樹(也叫B-樹)就是一種完全平衡的多叉樹,也就是說,每個葉子結點的高度都是一樣的。
首先我們先給出一張 B 樹的圖,並且介紹 B 樹的一些基本性質。

  • 一個結點如果有 \(k\) 個索引,那麼它就有 \(k+1\) 個孩子。索引和孩子的排列方式與 BST 類似。
  • 一個結點不能無限制地擁有索引。若我們稱一棵樹是 \(m\) 階 B 樹,那麼對根結點有 \(1\leqslant k\leqslant m-1\),對其他結點有 \(\left\lceil\dfrac{m}{2}\right\rceil-1\leqslant k\leqslant m-1\)。比如上圖是一棵 5 階 B 樹,那麼除根節點外,每個節點至少有 2 個索引,至多有 4 個索引。但是根節點的索引可以更少,比如上圖的根結點只有 1 個索引。
  • 3 階 B 樹也叫做 2-3 樹,4 階 B 樹也叫做 2-3-4 樹。可以以此類推,但是階數再高就沒人這麼叫了。

那麼我們接下來就介紹 B 樹的相關操作。
只介紹一些前置操作和插入刪除,剩下的還是同 BST。

1. split

當一個結點的索引數量過多時,我們需要對這個結點進行 split 操作。
當然這個操作很簡單,我們只需要找出來索引的最接近中位數的數,把它提出來就行了。
圖示:
image
如圖是一棵 2-3 樹,這個時候我們需要對紅框框出的結點進行分裂。我們把 6 提出來:
image
然後我們發現父親結點又超了。於是繼續分裂。
image
完成。

2. rotate

當一個結點的索引數量過少,並且它的兄弟結點(狹義,僅指左兄弟和右兄弟)的索引數量足夠多時,我們使用 rotate 操作。實際操作的時候,我們直接找索引數量多的兄弟結點進行 rotate。
文字描述不方便,直接上圖:
image
這是一棵 5 階 B 樹。這個地方我們要刪除 2,但是刪除之後結點的索引個數就過少了。同時我們發現它的右兄弟有足足 3 個索引,即使去掉一個也是滿足要求的。於是我們進行這樣的操作:
image
image
就像左旋一樣那我們就叫它左旋好了
另外一個方向的旋轉同理。

3. merge

但是我們會發現,有的時候兩個兄弟結點的索引數量都不夠。這個時候我們就要進行 merge 操作。
簡單地說,就是把左右結點連同索引結點合併成一個結點。因爲左右結點的索引數量都足夠少,很容易發現合併後的結點不需要再次分裂。事實上,有 \(\left(\left\lceil\dfrac{m}{2}\right\rceil-1\right)+\left(\left\lceil\dfrac{m}{2}\right\rceil-2\right)+1=\left(2\left\lceil\dfrac{m}{2}\right\rceil-1\right)-1\leqslant m-1\)
還是上圖:
image
這是一棵 5 階 B 樹。容易發現此時左結點索引數量過少,並且右結點的索引個數也不足以支持 rotate 操作。
於是我們進行 merge 操作,將左右結點和中間的索引進行合併,合併成一個結點。
image
注意圖中的情況比較特殊。因爲這個操作拿走了父親結點的一個索引,所以可能會導致父親結點的索引數量過少,此時我們還需要對父親結點進行 rotate/merge,才能保證性質不被破壞。

講完了前置操作,接下來就是平衡樹的正統操作了。

4. insert

學會了 split 之後這個操作應該是顯然的。找到對應結點進行插入,如果索引數量過多直接 split 即可。

5. delete

相對應地,delete 操作就複雜許多(連前置操作都是兩個)。分類討論:

  • 如果當前結點是葉子結點:直接刪除,如果索引個數過少就 rotate/merge。
  • 如果當前結點是內部結點:
    • 考慮左子樹的最大值所在結點,若結點的索引數量足夠大那麼直接把結點提上來當做新的索引。然後這就是一個刪除葉子結點的操作。(右子樹同理)
    • 如果兩個兒子索引個數都過少,則需要先 merge 兩個兒子。
    • 如果刪完之後索引個數還是過少,那還是要 rotate/merge。

內部結點的刪除並不是顯然的。還是進行圖解。
image
這是一棵 2-3 樹。下面我們要刪除 6。
我們發現 5 和 7 所在的結點索引數量都不夠。那不妨取左邊的 5 做一次交換。
image
然後接下來就是刪除葉節點 5 的操作了。兄弟結點的索引數量過少,考慮 merge,這裏就是把 3 和 4 合併。
image
刪除操作完成。
在上圖的基礎上我們再刪除 2。容易發現這個時候 3 所在的結點索引數量足夠多,因此直接把 3 提上來就行。
image
刪除完成。
我們再刪除 5:
image
首先交換沒有問題。
接下來合併。
image
我們發現又出現了一個索引數量過少的結點。
於是再次合併:
image
刪除操作完成。B樹就介紹到這裏。

2. 左偏紅黑樹

B 樹好是好,但是寫多叉樹就不能像二叉樹那樣好實現。結合兩者優點的方法是,將 B 樹的結構通過一種對應關係轉移到二叉樹上。

左偏紅黑樹是對 2-3 樹的二叉樹改造。

3. 紅黑樹

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