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 //迴圈到最後根節點,黑色 }