紅黑樹

爱跑步的乌龟發表於2024-07-20
package main

//定義常量紅黑
const (
    RED   = true
    BLACK = false
)

//紅黑樹結構
type RBNode struct {
    Left   *RBNode //左節點
    Right  *RBNode //右邊節點
    Parent *RBNode //父親節點
    Color  bool    //顏色
    //DataItem interface{} //資料
    Item //資料介面
}

//資料介面
type Item interface {
    Less(than Item) bool
}

//紅黑樹
type RBtree struct {
    NIL   *RBNode
    Root  *RBNode
    count uint
}

//比大小
func less(x, y Item) bool {
    return x.Less(y)
}

//初始化記憶體
func NewRBTree() *RBtree {
    return new(RBtree).Init()
}

//初始化紅黑樹
func (rbt *RBtree) Init() *RBtree {
    node := &RBNode{nil, nil, nil, BLACK, nil}
    return &RBtree{node, node, 0}
}

//獲取紅黑樹長度
func (rbt *RBtree) Len() uint {
    return rbt.count
}

//取得紅黑樹的極大值節點
func (rbt *RBtree) max(x *RBNode) *RBNode {
    if x == rbt.NIL {
        return rbt.NIL
    }
    for x.Right != rbt.NIL {
        x = x.Right
    }
    return x
}

//取得紅黑樹的極小值
func (rbt *RBtree) min(x *RBNode) *RBNode {
    if x == rbt.NIL {
        return rbt.NIL
    }
    for x.Left != rbt.NIL {
        x = x.Left
    }
    return x
}

//搜尋紅黑樹
func (rbt *RBtree) search(x *RBNode) *RBNode {
    pnode := rbt.Root //根節點
    for pnode != rbt.NIL {
        if less(pnode.Item, x.Item) {
            pnode = pnode.Right
        } else if less(x.Item, pnode.Item) {
            pnode = pnode.Left
        } else {
            break //找到
        }
    }
    return pnode
}

func (rbt *RBtree) leftRotate(x *RBNode) {
    if x.Right == rbt.NIL {
        return //左旋轉,逆時針,右孩子不可以為0
    }
    y := x.Right
    x.Right = y.Left //實現旋轉的左旋
    if y.Left != rbt.NIL {
        y.Left.Parent = x //設定父親節點
    }
    y.Parent = x.Parent //傳遞父節點
    if x.Parent == rbt.NIL {
        //根節點
        rbt.Root = y
    } else if x == x.Parent.Left { //x在根節點左邊
        x.Parent.Left = y
    } else { //x在根節點右邊
        x.Parent.Right = y
    }
    y.Left = x
    x.Parent = y

}
func (rbt *RBtree) rightRotate(x *RBNode) {
    if x.Left == nil {
        return //右邊旋轉,左子樹不可以為空
    }
    y := x.Left
    x.Left = y.Right
    if y.Right != rbt.NIL {
        y.Right.Parent = x //設定祖先
    }
    y.Parent = x.Parent //y儲存x的父親節點
    if x.Parent == rbt.NIL {
        rbt.Root = y
    } else if x == x.Parent.Left { //x小於根節點
        x.Parent.Left = y //父親節點的孩子是x,改。父親節點孩子y
    } else { //x大於根節點
        x.Parent.Right = y
    }
    y.Right = x
    x.Parent = y

}

//插入一條資料
func (rbt *RBtree) Insert(item Item) *RBNode {
    if item == nil {
        return nil
    }
    return rbt.insert(&RBNode{rbt.NIL, rbt.NIL, rbt.NIL, RED, item})
}

//插入
func (rbt *RBtree) insert(z *RBNode) *RBNode {

    //尋找插入位置
    x := rbt.Root
    y := rbt.NIL

    for x != rbt.NIL {
        y = x                     //備份位置,資料插入x,y之間
        if less(z.Item, x.Item) { //小於
            x = x.Left
        } else if less(x.Item, z.Item) { //大於
            x = x.Right
        } else { //相等
            return x //資料已經存在,無法插入
        }
    }
    z.Parent = y

    if y == rbt.NIL {
        rbt.Root = z
    } else if less(z.Item, y.Item) {
        y.Left = z //小於左邊插入
    } else {
        y.Right = z //大於右邊插入
    }
    rbt.count++
    rbt.insertFixup(z) //調整平衡
    return z

}

//插入之後,調整平衡
func (rbt *RBtree) insertFixup(z *RBNode) {
    for z.Parent.Color == RED { //一直迴圈下去,直到根節點
        if z.Parent == z.Parent.Parent.Left { //父親節點在爺爺左邊
            y := z.Parent.Parent.Right
            if y.Color == RED { //判斷大伯節點紅色,黑色

                z.Parent.Color = BLACK
                y.Color = BLACK
                z.Parent.Parent.Color = RED
                z = z.Parent.Parent //迴圈前進

            } else {
                if z == z.Parent.Right { //z比父親小
                    z = z.Parent
                    rbt.leftRotate(z) //左旋

                } else { //z比父親大
                    z.Parent.Color = BLACK
                    z.Parent.Parent.Color = RED
                    rbt.rightRotate(z.Parent.Parent)
                }
            }

        } else { // //父親節點在爺爺右邊
            y := z.Parent.Parent.Left //叔叔節點
            if y.Color == RED {       //判斷大伯節點紅色,黑色
                z.Parent.Color = BLACK
                y.Color = BLACK
                z.Parent.Parent.Color = RED
                z = z.Parent.Parent //迴圈前進
            } else {
                if z == z.Parent.Left {
                    z = z.Parent
                    rbt.rightRotate(z)
                } else {
                    z.Parent.Color = BLACK
                    z.Parent.Parent.Color = RED
                    rbt.leftRotate(z.Parent.Parent)
                }

            }
        }
    }
    rbt.Root.Color = BLACK
}
func (rbt *RBtree) GetDepth() int {
    var getDeepth func(node *RBNode) int //函式

    //函式包含
    getDeepth = func(node *RBNode) int {
        if node == nil {
            return 0
        }
        if node.Left == nil && node.Right == nil {
            return 1
        }
        var leftdeep int = getDeepth(node.Left)
        var rightdeep int = getDeepth(node.Right)
        if leftdeep > rightdeep {
            return leftdeep + 1
        } else {
            return rightdeep + 1
        }
    }
    return getDeepth(rbt.Root)

}

//近似查詢
func (rbt *RBtree) searchle(x *RBNode) *RBNode {
    p := rbt.Root //根節點
    n := p        //備份根節點
    for n != rbt.NIL {
        if less(n.Item, x.Item) {
            p = n
            n = n.Right //大於
        } else if less(x.Item, n.Item) {
            p = n
            n = n.Left //小於
        } else {
            return n
            break //跳出迴圈
        }
    }
    if less(p.Item, x.Item) {
        return p
    }
    p = rbt.desuccessor(p) //近似處理
    return p
}
func (rbt *RBtree) successor(x *RBNode) *RBNode {
    if x == rbt.NIL {
        return rbt.NIL
    }
    if x.Right != rbt.NIL {
        return rbt.min(x.Right) //取得右邊最小
    }
    y := x.Parent
    for y != rbt.NIL && x == y.Right {
        x = y
        y = y.Parent
    }
    return y

}
func (rbt *RBtree) desuccessor(x *RBNode) *RBNode {
    if x == rbt.NIL {
        return rbt.NIL
    }
    if x.Left != rbt.NIL {
        return rbt.max(x.Left) //取得左邊最大
    }
    y := x.Parent
    for y != rbt.NIL && x == y.Left {
        x = y
        y = y.Parent
    }
    return y
}

//最小,最大,查詢,修改,近似查詢
func (rbt *RBtree) Delete(item Item) Item {
    if item == nil {
        return nil
    }
    return rbt.delete(&RBNode{rbt.NIL, rbt.NIL, rbt.NIL, RED, item}).Item
}

func (rbt *RBtree) delete(key *RBNode) *RBNode {
    z := rbt.search(key) //尋找要刪除的節點
    if z == rbt.NIL {
        return rbt.NIL //無需刪除
    }
    //新建節點下,x,y備份,夾逼
    var x *RBNode
    var y *RBNode

    //節點
    ret := &RBNode{rbt.NIL, rbt.NIL, rbt.NIL, z.Color, z.Item}

    if z.Left == rbt.NIL || z.Right == rbt.NIL {
        y = z //單節點,y,z重合
    } else {
        y = rbt.successor(z) //找到最接近的右邊最小
    }

    if y.Left != rbt.NIL {
        x = y.Left
    } else {
        x = y.Right
    }
    x.Parent = y.Parent

    if y.Parent == rbt.NIL {
        rbt.Root = x
    } else if y == y.Parent.Left {
        y.Parent.Left = x
    } else {
        y.Parent.Right = x
    }

    if y != z {
        z.Item = y.Item
    }
    if y.Color == BLACK {
        rbt.deleteFixup(x)
    }

    rbt.count--
    return ret

}

//刪除時的紅黑修復需要考慮四種情況(下面的“X”指取代了被刪節點位置的新節點)
// (1) X的兄弟節點是紅色的:
//        |                              |
//       1●                             3●
//       / \             --------\      / \
// X-> 2●   ○3 <-brother --------/    1○   ●5
//         / \                        / \
//       4●   ●5                X-> 2●   ●4
//
// (2) X的兄弟節點是黑色的,而且兄弟節點的兩個孩子都是黑色的:
//        |                              |
//       1○                         X-> 1○
//       / \             --------\      / \
// X-> 2●   ●3 <-brother --------/    2●   ○3
//         / \                            / \
//       4●   ●5                        4●   ●5
//
// (3) X的兄弟節點是黑色的,兄弟的左孩子是紅色的,右孩子是黑色的:
//        |                              |
//       1○                             1○
//       / \             --------\      / \
// X-> 2●   ●3 <-brother --------/ X->2●   ●4
//         / \                              \
//       4○   ●5                             ○3
//                                            \
//                                             ●5
//
// (4) X的兄弟節點是黑色的,兄弟的右孩子是紅色的:
//        |                              |
//       1○                             3○   X->root and loop while end
//       / \             --------\      / \
// X-> 2●   ●3 <-brother --------/    1●   ●5
//         / \                        / \
//       4○   ○5                    2●   ○4
//
//以上是兄弟節點在X右邊時的情況,在X左邊是取相反即可!
func (rbt *RBtree) deleteFixup(x *RBNode) {
    for x != rbt.Root && x.Color == BLACK {
        if x == x.Parent.Left { //x在左邊
            w := x.Parent.Right //哥哥節點
            if w.Color == RED { //左邊旋轉
                w.Color = BLACK
                x.Parent.Color = RED
                rbt.leftRotate(x.Parent)
                w = x.Parent.Right //迴圈步驟
            }
            if w.Left.Color == BLACK && w.Right.Color == BLACK {
                w.Color = RED
                x = x.Parent //迴圈條件

            } else {
                if w.Right.Color == BLACK {
                    w.Left.Color = BLACK
                    w.Color = RED
                    rbt.rightRotate(w) //右旋轉
                    w = x.Parent.Right //迴圈條件
                }
                w.Color = x.Parent.Color
                x.Parent.Color = BLACK
                w.Right.Color = BLACK
                rbt.leftRotate(x.Parent)
                x = rbt.Root
            }

        } else { //x在右邊
            w := x.Parent.Left  //左邊節點
            if w.Color == RED { //左旋
                w.Color = BLACK
                x.Parent.Color = RED
                rbt.rightRotate(x.Parent)
                w = x.Parent.Right //迴圈步驟
            }
            if w.Left.Color == BLACK && w.Right.Color == BLACK {

                w.Color = RED
                x = x.Parent //迴圈條件
            } else {
                if w.Right.Color == BLACK {
                    w.Left.Color = BLACK
                    w.Color = RED
                    rbt.leftRotate(w) //右旋轉
                    w = x.Parent.Left //迴圈條件
                }
                w.Color = x.Parent.Color
                x.Parent.Color = BLACK
                w.Right.Color = BLACK
                rbt.rightRotate(x.Parent)
                x = rbt.Root

            }
        }

    }
    x.Color = BLACK //迴圈到最後根節點,黑色

}

相關文章