Skip to content

Commit

Permalink
RedBlack: provide InOrder function
Browse files Browse the repository at this point in the history
  • Loading branch information
obitech committed Jan 22, 2021
1 parent bf85b1c commit 3de1f81
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 26 deletions.
8 changes: 4 additions & 4 deletions redblack/delete.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package redblack

// Delete deletes a node with the given key.
func (t *RBTree) Delete(key Key) {
func (t *Tree) Delete(key Key) {
t.lock.Lock()
defer t.lock.Unlock()

Expand All @@ -10,7 +10,7 @@ func (t *RBTree) Delete(key Key) {
}
}

func (t *RBTree) delete(z *node) {
func (t *Tree) delete(z *node) {
var (
y = z
yOriginalColor = y.color
Expand Down Expand Up @@ -50,7 +50,7 @@ func (t *RBTree) delete(z *node) {
}
}

func (t *RBTree) transplant(u, v *node) {
func (t *Tree) transplant(u, v *node) {
switch {
case u.parent == t.sentinel:
t.root = v
Expand All @@ -63,7 +63,7 @@ func (t *RBTree) transplant(u, v *node) {
v.parent = u.parent
}

func (t *RBTree) fixupDelete(x *node) {
func (t *Tree) fixupDelete(x *node) {
for x != t.root && x.color == black {
if x == x.parent.left {
w := x.parent.right
Expand Down
6 changes: 3 additions & 3 deletions redblack/insert.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package redblack

// Upsert updates an existing payload, or inserts a new one with the given key.
func (t *RBTree) Upsert(key Key, payload interface{}) {
func (t *Tree) Upsert(key Key, payload interface{}) {
t.lock.Lock()
defer t.lock.Unlock()

Expand All @@ -12,7 +12,7 @@ func (t *RBTree) Upsert(key Key, payload interface{}) {
}
}

func (t *RBTree) insert(z *node) {
func (t *Tree) insert(z *node) {
var (
y = t.sentinel
x = t.root
Expand Down Expand Up @@ -45,7 +45,7 @@ func (t *RBTree) insert(z *node) {
t.fixupInsert(z)
}

func (t *RBTree) fixupInsert(z *node) {
func (t *Tree) fixupInsert(z *node) {
for z.parent.color == red {
if z.parent == z.parent.parent.left {
y := z.parent.parent.right
Expand Down
2 changes: 1 addition & 1 deletion redblack/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func TestRBTree_Upsert(t *testing.T) {
}

//
// func createTree(keys myInt) *RBTree {
// func createTree(keys myInt) *Tree {
// rand.Seed(time.Now().UnixNano())
// tree := NewRedBlackTree()
//
Expand Down
42 changes: 42 additions & 0 deletions redblack/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package redblack

// Result is a search result when looking up a Key in the tree.
type Result struct {
Key Key
Payload interface{}
}

// InOrder returns an ordered list of all entries.
func (t *Tree) InOrder() []Result {
t.lock.RLock()
defer t.lock.RUnlock()

if t.root == t.sentinel {
return nil
}

res := make([]Result, 0)

t.resultsInorder(t.root, &res)

return res
}

func (t *Tree) resultsInorder(z *node, res *[]Result) {
if z == t.sentinel {
return
}

if z.left != t.sentinel {
t.resultsInorder(z.left, res)
}

*res = append(*res, Result{
Key: z.key,
Payload: z.payload,
})

if z.right != t.sentinel {
t.resultsInorder(z.right, res)
}
}
34 changes: 17 additions & 17 deletions redblack/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import (

// NewRedBlackTree returns a new red-back tree. All operations on the tree are
// safe to be accessed concurrently.
func NewRedBlackTree() *RBTree {
func NewRedBlackTree() *Tree {
sentinel := &node{color: black, payload: "sentinel"}

return &RBTree{
return &Tree{
lock: sync.RWMutex{},
root: sentinel,
sentinel: sentinel,
}
}

// Root returns the payload of the root node of the tree.
func (t *RBTree) Root() interface{} {
func (t *Tree) Root() interface{} {
t.lock.RLock()
defer t.lock.RUnlock()

Expand All @@ -33,15 +33,15 @@ func (t *RBTree) Root() interface{} {

// Height returns the height (max depth) of the tree. Returns -1 if the tree
// has no nodes. A (rooted) tree with only a single node has a height of zero.
func (t *RBTree) Height() int {
func (t *Tree) Height() int {
t.lock.RLock()
defer t.lock.RUnlock()

return int(t.height(t.root))
}

// Min returns the payload of the lowest key, or nil.
func (t *RBTree) Min() interface{} {
func (t *Tree) Min() interface{} {
t.lock.RLock()
defer t.lock.RUnlock()

Expand All @@ -55,7 +55,7 @@ func (t *RBTree) Min() interface{} {
}

// Max returns the payload of the highest key, or nil.
func (t *RBTree) Max() interface{} {
func (t *Tree) Max() interface{} {
t.lock.RLock()
defer t.lock.RUnlock()

Expand All @@ -69,7 +69,7 @@ func (t *RBTree) Max() interface{} {
}

// Search returns the payload for a given key, or nil.
func (t *RBTree) Search(key Key) interface{} {
func (t *Tree) Search(key Key) interface{} {
t.lock.RLock()
defer t.lock.RUnlock()

Expand All @@ -88,7 +88,7 @@ func (t *RBTree) Search(key Key) interface{} {

// Successor returns the payload of the next highest neighbour (key-wise) of the
// passed key.
func (t *RBTree) Successor(key Key) interface{} {
func (t *Tree) Successor(key Key) interface{} {
t.lock.RLock()
defer t.lock.RUnlock()

Expand All @@ -101,15 +101,15 @@ func (t *RBTree) Successor(key Key) interface{} {
return n.payload
}

func (t *RBTree) height(node *node) float64 {
func (t *Tree) height(node *node) float64 {
if node == t.sentinel {
return -1
}

return 1 + math.Max(t.height(node.left), t.height(node.right))
}

func (t *RBTree) successor(z *node) *node {
func (t *Tree) successor(z *node) *node {
if z == t.sentinel {
return nil
}
Expand All @@ -128,23 +128,23 @@ func (t *RBTree) successor(z *node) *node {
return parent
}

func (t *RBTree) min(z *node) *node {
func (t *Tree) min(z *node) *node {
for z != t.sentinel && z.left != t.sentinel {
z = z.left
}

return z
}

func (t *RBTree) max(z *node) *node {
func (t *Tree) max(z *node) *node {
for z != t.sentinel && z.right != t.sentinel {
z = z.right
}

return z
}

func (t *RBTree) search(z *node, key Key) *node {
func (t *Tree) search(z *node, key Key) *node {
if z == t.sentinel || z.key == key {
return z
}
Expand All @@ -160,7 +160,7 @@ func (t *RBTree) search(z *node, key Key) *node {
return z
}

func (t *RBTree) rotateLeft(x *node) {
func (t *Tree) rotateLeft(x *node) {
// y's left subtree will be x's right subtree.
y := x.right
x.right = y.left
Expand All @@ -186,7 +186,7 @@ func (t *RBTree) rotateLeft(x *node) {
x.parent = y
}

func (t *RBTree) rotateRight(x *node) {
func (t *Tree) rotateRight(x *node) {
y := x.left
x.left = y.right

Expand All @@ -209,7 +209,7 @@ func (t *RBTree) rotateRight(x *node) {
x.parent = y
}

func (t *RBTree) newLeaf(key Key, p interface{}) *node {
func (t *Tree) newLeaf(key Key, p interface{}) *node {
return &node{
key: key,
payload: p,
Expand All @@ -218,6 +218,6 @@ func (t *RBTree) newLeaf(key Key, p interface{}) *node {
}
}

func (t *RBTree) isLeaf(z *node) bool {
func (t *Tree) isLeaf(z *node) bool {
return z.left == t.sentinel && z.right == t.sentinel
}
2 changes: 1 addition & 1 deletion redblack/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Key interface {

// Tree represents a red-black tree with a root node and Mutex to protect
// concurrent access.
type RBTree struct {
type Tree struct {
lock sync.RWMutex
root *node
sentinel *node
Expand Down

0 comments on commit 3de1f81

Please sign in to comment.