Skip to content

Commit

Permalink
Item becomes interface
Browse files Browse the repository at this point in the history
  • Loading branch information
petar committed Apr 27, 2013
1 parent fc4f3f4 commit c08868e
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 176 deletions.
4 changes: 2 additions & 2 deletions llrb/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func (t *Tree) ascendGreaterOrEqual(h *Node, pivot Item, iterator ItemIterator)
if h == nil {
return true
}
if !t.less(h.Item, pivot) {
if !h.Item.Less(pivot) {
if !t.ascendGreaterOrEqual(h.Left, pivot, iterator) {
return false
}
Expand All @@ -33,7 +33,7 @@ func (t *Tree) descendLessOrEqual(h *Node, pivot Item, iterator ItemIterator) bo
if h == nil {
return true
}
if t.less(h.Item, pivot) || !t.less(pivot, h.Item) {
if h.Item.Less(pivot) || !pivot.Less(h.Item) {
if !t.descendLessOrEqual(h.Right, pivot, iterator) {
return false
}
Expand Down
122 changes: 0 additions & 122 deletions llrb/iterator_deprecated.go

This file was deleted.

4 changes: 2 additions & 2 deletions llrb/llrb-stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ func (t *Tree) getHeight(h *Node, item Item) (Item, int) {
if h == nil {
return nil, 0
}
if t.less(item, h.Item) {
if item.Less(h.Item) {
result, depth := t.getHeight(h.Left, item)
return result, depth + 1
}
if t.less(h.Item, item) {
if h.Item.Less(item) {
result, depth := t.getHeight(h.Right, item)
return result, depth + 1
}
Expand Down
52 changes: 20 additions & 32 deletions llrb/llrb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees

package llrb

// Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees, based on:
// A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees,
// based on the following work:
//
// http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf
// http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
Expand All @@ -17,8 +14,10 @@ package llrb
// implementation of 2-3 trees is a recent improvement on the traditional implementation,
// observed and documented by Robert Sedgewick.
//
package llrb

// Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees
type Tree struct {
less LessFunc
count int
root *Node
}
Expand All @@ -30,22 +29,13 @@ type Node struct {
// In the LLRB, new nodes are always red, hence the zero-value for node
}

type Item interface{}

type LessFunc func(a, b interface{}) bool

// New() allocates a new tree
func New(lessfunc LessFunc) *Tree {
t := &Tree{}
t.Init(lessfunc)
return t
type Item interface {
Less(than Item) bool
}

// Init resets (empties) the tree
func (t *Tree) Init(lessfunc LessFunc) {
t.less = lessfunc
t.root = nil
t.count = 0
// New() allocates a new tree
func New() *Tree {
return &Tree{}
}

// SetRoot sets the root node of the tree.
Expand All @@ -63,21 +53,19 @@ func (t *Tree) Root() *Node {
// Len returns the number of nodes in the tree.
func (t *Tree) Len() int { return t.count }

// Has returns true if the tree contains an element
// whose LessThan order equals that of key.
// Has returns true if the tree contains an element whose order is the same as that of key.
func (t *Tree) Has(key Item) bool {
return t.Get(key) != nil
}

// Get retrieves an element from the tree whose LessThan order
// equals that of key.
// Get retrieves an element from the tree whose order is the same as that of key.
func (t *Tree) Get(key Item) Item {
h := t.root
for h != nil {
switch {
case t.less(key, h.Item):
case key.Less(h.Item):
h = h.Left
case t.less(h.Item, key):
case h.Item.Less(key):
h = h.Right
default:
return h.Item
Expand Down Expand Up @@ -145,9 +133,9 @@ func (t *Tree) replaceOrInsert(h *Node, item Item) (*Node, Item) {
h = walkDownRot23(h)

var replaced Item
if t.less(item, h.Item) { // BUG
if item.Less(h.Item) { // BUG
h.Left, replaced = t.replaceOrInsert(h.Left, item)
} else if t.less(h.Item, item) {
} else if h.Item.Less(item) {
h.Right, replaced = t.replaceOrInsert(h.Right, item)
} else {
replaced, h.Item = h.Item, item
Expand Down Expand Up @@ -176,7 +164,7 @@ func (t *Tree) insertNoReplace(h *Node, item Item) *Node {

h = walkDownRot23(h)

if t.less(item, h.Item) {
if item.Less(h.Item) {
h.Left = t.insertNoReplace(h.Left, item)
} else {
h.Right = t.insertNoReplace(h.Right, item)
Expand Down Expand Up @@ -312,7 +300,7 @@ func (t *Tree) delete(h *Node, item Item) (*Node, Item) {
if h == nil {
return nil, nil
}
if t.less(item, h.Item) {
if item.Less(h.Item) {
if h.Left == nil { // item not present. Nothing to delete
return h, nil
}
Expand All @@ -325,15 +313,15 @@ func (t *Tree) delete(h *Node, item Item) (*Node, Item) {
h = rotateRight(h)
}
// If @item equals @h.Item and no right children at @h
if !t.less(h.Item, item) && h.Right == nil {
if !h.Item.Less(item) && h.Right == nil {
return nil, h.Item
}
// PETAR: Added 'h.Right != nil' below
if h.Right != nil && !isRed(h.Right) && !isRed(h.Right.Left) {
h = moveRedRight(h)
}
// If @item equals @h.Item, and (from above) 'h.Right != nil'
if !t.less(h.Item, item) {
if !h.Item.Less(item) {
var subDeleted Item
h.Right, subDeleted = deleteMin(h.Right)
if subDeleted == nil {
Expand Down
28 changes: 10 additions & 18 deletions llrb/llrb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,39 @@ import (
"testing"
)

func IntLess(p, q interface{}) bool {
return p.(int) < q.(int)
}

func StringLess(p, q interface{}) bool {
return p.(string) < q.(string)
}

func TestCases(t *testing.T) {
tree := New(IntLess)
tree.ReplaceOrInsert(1)
tree.ReplaceOrInsert(1)
tree := New()
tree.ReplaceOrInsert(Int(1))
tree.ReplaceOrInsert(Int(1))
if tree.Len() != 1 {
t.Errorf("expecting len 1")
}
if !tree.Has(1) {
if !tree.Has(Int(1)) {
t.Errorf("expecting to find key=1")
}

tree.Delete(1)
tree.Delete(Int(1))
if tree.Len() != 0 {
t.Errorf("expecting len 0")
}
if tree.Has(1) {
if tree.Has(Int(1)) {
t.Errorf("not expecting to find key=1")
}

tree.Delete(1)
tree.Delete(Int(1))
if tree.Len() != 0 {
t.Errorf("expecting len 0")
}
if tree.Has(1) {
if tree.Has(Int(1)) {
t.Errorf("not expecting to find key=1")
}
}

func TestReverseInsertOrder(t *testing.T) {
tree := New(IntLess)
tree := New()
n := 100
for i := 0; i < n; i++ {
tree.ReplaceOrInsert(n - i)
tree.ReplaceOrInsert(Int(n - i))
}
c := tree.IterAscend()
for j, item := 1, <-c; item != nil; j, item = j+1, <-c {
Expand Down
17 changes: 17 additions & 0 deletions llrb/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2010 Petar Maymounkov. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package llrb

type Int int

func (x Int) Less(than Item) bool {
return x < than.(Int)
}

type String string

func (x String) Less(than Item) bool {
return x < than.(String)
}

0 comments on commit c08868e

Please sign in to comment.