1. 程式人生 > >AA樹,2-3樹二叉化

AA樹,2-3樹二叉化

AA樹,紅黑樹的變種
CLRS(演算法導論)上對RBT(紅黑樹,red-black tree)的講解相當好;
我這裡只能東施效顰,解釋一下紅黑樹的變種,AA樹;
正如RBT是由2-3-4樹演化而來,AA樹是2-3樹的二叉形式;
給出AA樹的定義:
1. AA樹是一顆維護了結點顏色(黑高)的二叉搜尋樹;
2. 任意一葉結點(T.nil,哨兵)到根結點路徑上黑結點個數相同(黑高相等,平衡原理);
3. 根結點為黑,葉結點(T.nil,哨兵)顏色為黑;
4. 紅結點兩子結點顏色為黑(子結點可能為葉結點);
5. 紅結點不得作為黑結點左子結點(與RBT不同);
給出一個AA樹樣例:
AA樹樣例


為了分析方便,我們把樣例轉化為類2-3樹形式,以便分析:
AA樹2-3化
網上介紹AA樹大部分都是維護了結點的黑高;
我這裡沿用RBT的形式,維護結點的顏色;
AA樹中的搜尋很顯然,與普通二叉搜尋樹一樣;
下面給出兩個大頭:插入與刪除;
插入:
參考CLRS,給出虛擬碼:

Inset(T,t)
    y=T.nil
    x=T.root
    while x≠T.nil
        y=x
        if t.key<x.key
            x=x.left
        else x=x.right
    t.p=y
    if y
==T.nil T.root=t else if t.key<y.key y.left=t else y.right=t t.left=T.nil t.right=T.nil t.color=red Insert-Fixup(t)

這是插入的迭代寫法,考慮到迭代並不複雜,效率也很高,維護,除錯也方便,我這裡就不給出遞迴形式;
Insert中有一個Insert-Fixup,它是一個輔助過程,修復被破壞的紅黑性質;
修復的情況:
case 1: 紅結點做了其父左子結點 ,其中D,E結點顏色未知;
這裡寫圖片描述


Case 1’ : D結點為黑
這裡寫圖片描述
操作: 右旋x父結點後兩結點顏色互換,並將x指向原父結點;
這裡寫圖片描述
Case 1”: D結點為紅
這裡寫圖片描述
操作: 右旋父結點,剩下的交給Case 2處理;
這裡寫圖片描述
Case 2: 紅結點右子結點為紅
這裡寫圖片描述
操作: 左旋x的父結點後將x的右結點變為黑色;
這裡寫圖片描述

以上操作完成後可能造成新的紅黑性質破壞,故x結點上移;
最後,將根結點顏色設為黑,修復完畢;
綜合考慮,給出Insert-Fixup虛擬碼:

Insert-Fixup(T,t)
    while t.color==red
        if y==t.pre.left
            right-rotate(t.pre)
            if t.right.color==black
                t.color=black
                t.right.color=red
            else t=t.right
        if t.right.color==red
            left-rotate(t.pre)
            t.right.color=black
        t=t.pre
    T.root.color=black

給出一個AA樹插入例項:

樣例插入結點8:
這裡寫圖片描述
經Case 2 變為:
這裡寫圖片描述
經Case 1’變為:
這裡寫圖片描述
再經Case 2 變為:
這裡寫圖片描述
經Case 1” 變為:
這裡寫圖片描述
經Case 2 變為:
這裡寫圖片描述
最後,設定根結點顏色:
這裡寫圖片描述
好,介紹完了插入操作,下面是刪除操作; 我的刪除操作討論的情況很多,但保證正確清晰; 直接給出刪除和其呼叫的子過程的虛擬碼:

Transplant(T,x,y)
    if x.pre==T.nil
            T.root=y
    else
        if x==x.pre.left
            x.pre.left=y
        else x.pre.right=y
    if y≠T.nil
        y.pre=x.pre

好,我的刪除太醜了,等我再改改;