init
This commit is contained in:
426
dtask/pkg/rbtree/rbtree.go
Normal file
426
dtask/pkg/rbtree/rbtree.go
Normal file
@@ -0,0 +1,426 @@
|
||||
// Copyright 2015, Hu Keping . All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package rbtree implements operations on Red-Black tree.
|
||||
package rbtree
|
||||
|
||||
//
|
||||
// Red-Black tree properties: http://en.wikipedia.org/wiki/Rbtree
|
||||
//
|
||||
// 1) A node is either red or black
|
||||
// 2) The root is black
|
||||
// 3) All leaves (NULL) are black
|
||||
// 4) Both children of every red node are black
|
||||
// 5) Every simple path from root to leaves contains the same number
|
||||
// of black nodes.
|
||||
//
|
||||
|
||||
// Node of the rbtree has a pointer of the node of parent, left, right, also has own color and Item which client uses
|
||||
type Node struct {
|
||||
Left *Node
|
||||
Right *Node
|
||||
Parent *Node
|
||||
Color uint
|
||||
|
||||
// for use by client.
|
||||
Item
|
||||
}
|
||||
|
||||
const (
|
||||
// RED represents the color of the node is red
|
||||
RED = 0
|
||||
// BLACK represents the color of the node is black
|
||||
BLACK = 1
|
||||
)
|
||||
|
||||
// Item has a method to compare items which is less
|
||||
type Item interface {
|
||||
Less(than Item) bool
|
||||
}
|
||||
|
||||
// Rbtree represents a Red-Black tree.
|
||||
type Rbtree struct {
|
||||
NIL *Node
|
||||
root *Node
|
||||
count uint
|
||||
}
|
||||
|
||||
func less(x, y Item) bool {
|
||||
return x.Less(y)
|
||||
}
|
||||
|
||||
// New returns an initialized Red-Black tree
|
||||
func New() *Rbtree { return new(Rbtree).Init() }
|
||||
|
||||
// Init returns the initial of rbtree
|
||||
func (t *Rbtree) Init() *Rbtree {
|
||||
node := &Node{nil, nil, nil, BLACK, nil}
|
||||
return &Rbtree{
|
||||
NIL: node,
|
||||
root: node,
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Rbtree) leftRotate(x *Node) {
|
||||
// Since we are doing the left rotation, the right child should *NOT* nil.
|
||||
if x.Right == t.NIL {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// The illation of left rotation
|
||||
//
|
||||
// | |
|
||||
// X Y
|
||||
// / \ left rotate / \
|
||||
// α Y -------------> X γ
|
||||
// / \ / \
|
||||
// β γ α β
|
||||
//
|
||||
// It should be note that during the rotating we do not change
|
||||
// the Nodes' color.
|
||||
//
|
||||
y := x.Right
|
||||
x.Right = y.Left
|
||||
if y.Left != t.NIL {
|
||||
y.Left.Parent = x
|
||||
}
|
||||
y.Parent = x.Parent
|
||||
|
||||
if x.Parent == t.NIL {
|
||||
t.root = y
|
||||
} else if x == x.Parent.Left {
|
||||
x.Parent.Left = y
|
||||
} else {
|
||||
x.Parent.Right = y
|
||||
}
|
||||
|
||||
y.Left = x
|
||||
x.Parent = y
|
||||
}
|
||||
|
||||
func (t *Rbtree) rightRotate(x *Node) {
|
||||
// Since we are doing the right rotation, the left child should *NOT* nil.
|
||||
if x.Left == t.NIL {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// The illation of right rotation
|
||||
//
|
||||
// | |
|
||||
// X Y
|
||||
// / \ right rotate / \
|
||||
// Y γ -------------> α X
|
||||
// / \ / \
|
||||
// α β β γ
|
||||
//
|
||||
// It should be note that during the rotating we do not change
|
||||
// the Nodes' color.
|
||||
//
|
||||
y := x.Left
|
||||
x.Left = y.Right
|
||||
if y.Right != t.NIL {
|
||||
y.Right.Parent = x
|
||||
}
|
||||
y.Parent = x.Parent
|
||||
|
||||
if x.Parent == t.NIL {
|
||||
t.root = y
|
||||
} else if x == x.Parent.Left {
|
||||
x.Parent.Left = y
|
||||
} else {
|
||||
x.Parent.Right = y
|
||||
}
|
||||
|
||||
y.Right = x
|
||||
x.Parent = y
|
||||
}
|
||||
|
||||
func (t *Rbtree) insert(z *Node) *Node {
|
||||
x := t.root
|
||||
y := t.NIL
|
||||
|
||||
for x != t.NIL {
|
||||
y = x
|
||||
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 == t.NIL {
|
||||
t.root = z
|
||||
} else if less(z.Item, y.Item) {
|
||||
y.Left = z
|
||||
} else {
|
||||
y.Right = z
|
||||
}
|
||||
|
||||
t.count++
|
||||
t.insertFixup(z)
|
||||
return z
|
||||
}
|
||||
|
||||
func (t *Rbtree) insertFixup(z *Node) {
|
||||
for z.Parent.Color == RED {
|
||||
//
|
||||
// Howerver, we do not need the assertion of non-nil grandparent
|
||||
// because
|
||||
//
|
||||
// 2) The root is black
|
||||
//
|
||||
// Since the color of the parent is RED, so the parent is not root
|
||||
// and the grandparent must be exist.
|
||||
//
|
||||
if z.Parent == z.Parent.Parent.Left {
|
||||
// Take y as the uncle, although it can be NIL, in that case
|
||||
// its color is BLACK
|
||||
y := z.Parent.Parent.Right
|
||||
if y.Color == RED {
|
||||
//
|
||||
// Case 1:
|
||||
// Parent and uncle are both RED, the grandparent must be BLACK
|
||||
// due to
|
||||
//
|
||||
// 4) Both children of every red node are black
|
||||
//
|
||||
// Since the current node and its parent are all RED, we still
|
||||
// in violation of 4), So repaint both the parent and the uncle
|
||||
// to BLACK and grandparent to RED(to maintain 5)
|
||||
//
|
||||
// 5) Every simple path from root to leaves contains the same
|
||||
// number of black nodes.
|
||||
//
|
||||
z.Parent.Color = BLACK
|
||||
y.Color = BLACK
|
||||
z.Parent.Parent.Color = RED
|
||||
z = z.Parent.Parent
|
||||
} else {
|
||||
if z == z.Parent.Right {
|
||||
//
|
||||
// Case 2:
|
||||
// Parent is RED and uncle is BLACK and the current node
|
||||
// is right child
|
||||
//
|
||||
// A left rotation on the parent of the current node will
|
||||
// switch the roles of each other. This still leaves us in
|
||||
// violation of 4).
|
||||
// The continuation into Case 3 will fix that.
|
||||
//
|
||||
z = z.Parent
|
||||
t.leftRotate(z)
|
||||
}
|
||||
//
|
||||
// Case 3:
|
||||
// Parent is RED and uncle is BLACK and the current node is
|
||||
// left child
|
||||
//
|
||||
// At the very beginning of Case 3, current node and parent are
|
||||
// both RED, thus we violate 4).
|
||||
// Repaint parent to BLACK will fix it, but 5) does not allow
|
||||
// this because all paths that go through the parent will get
|
||||
// 1 more black node. Then repaint grandparent to RED (as we
|
||||
// discussed before, the grandparent is BLACK) and do a right
|
||||
// rotation will fix that.
|
||||
//
|
||||
z.Parent.Color = BLACK
|
||||
z.Parent.Parent.Color = RED
|
||||
t.rightRotate(z.Parent.Parent)
|
||||
}
|
||||
} else { // same as then clause with "right" and "left" exchanged
|
||||
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
|
||||
t.rightRotate(z)
|
||||
}
|
||||
z.Parent.Color = BLACK
|
||||
z.Parent.Parent.Color = RED
|
||||
t.leftRotate(z.Parent.Parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.root.Color = BLACK
|
||||
}
|
||||
|
||||
// Just traverse the node from root to left recursively until left is NIL.
|
||||
// The node whose left is NIL is the node with minimum value.
|
||||
func (t *Rbtree) min(x *Node) *Node {
|
||||
if x == t.NIL {
|
||||
return t.NIL
|
||||
}
|
||||
|
||||
for x.Left != t.NIL {
|
||||
x = x.Left
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Just traverse the node from root to right recursively until right is NIL.
|
||||
// The node whose right is NIL is the node with maximum value.
|
||||
func (t *Rbtree) max(x *Node) *Node {
|
||||
if x == t.NIL {
|
||||
return t.NIL
|
||||
}
|
||||
|
||||
for x.Right != t.NIL {
|
||||
x = x.Right
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func (t *Rbtree) search(x *Node) *Node {
|
||||
p := t.root
|
||||
|
||||
for p != t.NIL {
|
||||
if less(p.Item, x.Item) {
|
||||
p = p.Right
|
||||
} else if less(x.Item, p.Item) {
|
||||
p = p.Left
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
//TODO: Need Document
|
||||
func (t *Rbtree) successor(x *Node) *Node {
|
||||
if x == t.NIL {
|
||||
return t.NIL
|
||||
}
|
||||
|
||||
// Get the minimum from the right sub-tree if it existed.
|
||||
if x.Right != t.NIL {
|
||||
return t.min(x.Right)
|
||||
}
|
||||
|
||||
y := x.Parent
|
||||
for y != t.NIL && x == y.Right {
|
||||
x = y
|
||||
y = y.Parent
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
//TODO: Need Document
|
||||
func (t *Rbtree) delete(key *Node) *Node {
|
||||
z := t.search(key)
|
||||
|
||||
if z == t.NIL {
|
||||
return t.NIL
|
||||
}
|
||||
ret := &Node{t.NIL, t.NIL, t.NIL, z.Color, z.Item}
|
||||
|
||||
var y *Node
|
||||
var x *Node
|
||||
|
||||
if z.Left == t.NIL || z.Right == t.NIL {
|
||||
y = z
|
||||
} else {
|
||||
y = t.successor(z)
|
||||
}
|
||||
|
||||
if y.Left != t.NIL {
|
||||
x = y.Left
|
||||
} else {
|
||||
x = y.Right
|
||||
}
|
||||
|
||||
// Even if x is NIL, we do the assign. In that case all the NIL nodes will
|
||||
// change from {nil, nil, nil, BLACK, nil} to {nil, nil, ADDR, BLACK, nil},
|
||||
// but do not worry about that because it will not affect the compare
|
||||
// between Node-X with Node-NIL
|
||||
x.Parent = y.Parent
|
||||
|
||||
if y.Parent == t.NIL {
|
||||
t.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 {
|
||||
t.deleteFixup(x)
|
||||
}
|
||||
|
||||
t.count--
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (t *Rbtree) deleteFixup(x *Node) {
|
||||
for x != t.root && x.Color == BLACK {
|
||||
if x == x.Parent.Left {
|
||||
w := x.Parent.Right
|
||||
if w.Color == RED {
|
||||
w.Color = BLACK
|
||||
x.Parent.Color = RED
|
||||
t.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
|
||||
t.rightRotate(w)
|
||||
w = x.Parent.Right
|
||||
}
|
||||
w.Color = x.Parent.Color
|
||||
x.Parent.Color = BLACK
|
||||
w.Right.Color = BLACK
|
||||
t.leftRotate(x.Parent)
|
||||
// this is to exit while loop
|
||||
x = t.root
|
||||
}
|
||||
} else { // the code below is has left and right switched from above
|
||||
w := x.Parent.Left
|
||||
if w.Color == RED {
|
||||
w.Color = BLACK
|
||||
x.Parent.Color = RED
|
||||
t.rightRotate(x.Parent)
|
||||
w = x.Parent.Left
|
||||
}
|
||||
if w.Left.Color == BLACK && w.Right.Color == BLACK {
|
||||
w.Color = RED
|
||||
x = x.Parent
|
||||
} else {
|
||||
if w.Left.Color == BLACK {
|
||||
w.Right.Color = BLACK
|
||||
w.Color = RED
|
||||
t.leftRotate(w)
|
||||
w = x.Parent.Left
|
||||
}
|
||||
w.Color = x.Parent.Color
|
||||
x.Parent.Color = BLACK
|
||||
w.Left.Color = BLACK
|
||||
t.rightRotate(x.Parent)
|
||||
x = t.root
|
||||
}
|
||||
}
|
||||
}
|
||||
x.Color = BLACK
|
||||
}
|
||||
Reference in New Issue
Block a user