Skip to content

Commit

Permalink
stree: add a Find method
Browse files Browse the repository at this point in the history
This is similar to Cursor, but selects the first key greater than or equal to
the given key rather than failing when the exact key is not found.
  • Loading branch information
creachadair committed Jan 5, 2025
1 parent d46aeb9 commit bd85c99
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
10 changes: 10 additions & 0 deletions stree/stree.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ func (t *Tree[T]) Get(key T) (_ T, ok bool) {
return
}

// Find returns a cursor to the smallest key in the tree greater than or equal
// to key. If no such key exists, Find returns nil.
func (t *Tree[T]) Find(key T) *Cursor[T] {
path := t.root.pathTo(key, t.compare)
if len(path) == 0 || t.compare(path[len(path)-1].X, key) < 0 {
return nil
}
return &Cursor[T]{path: path}
}

// Inorder is a range function that visits each key of t in order.
func (t *Tree[T]) Inorder(yield func(key T) bool) { t.root.inorder(yield) }

Expand Down
39 changes: 39 additions & 0 deletions stree/stree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,45 @@ func TestCursor(t *testing.T) {
t.Errorf("Right tree (-got, +want):\n%s", diff)
}
})

t.Run("Find", func(t *testing.T) {
tree := stree.New(250, strings.Compare, "a", "e", "i", "o", "u")

t.Run("None", func(t *testing.T) {
if got := tree.Find("z"); got != nil {
t.Errorf("Find z: got %v, want nil", got)
}
})
t.Run("Exact", func(t *testing.T) {
if got := tree.Find("e"); got.Key() != "e" {
t.Errorf("Find e: got %q, want e", got.Key())
}
})
t.Run("Before", func(t *testing.T) {
got := tree.Find("0")
if got.Key() != "a" {
t.Errorf("Find 0: got %q, want a", got.Key())
}
if next := got.Next(); next.Key() != "e" {
t.Errorf("Next a: got %q, want e", next.Key())
}
if prev := got.Prev().Prev(); prev.Valid() {
t.Errorf("Prev a: got %v, want invalid", prev)
}
})
t.Run("Between", func(t *testing.T) {
got := tree.Find("k")
if got.Key() != "o" {
t.Errorf("Find k: got %q, want o", got.Key())
}
if next := got.Next(); next.Key() != "u" {
t.Errorf("Next o: got %q, want u", next.Key())
}
if prev := got.Prev().Prev(); prev.Key() != "i" {
t.Errorf("Prev o: got %q, want i", prev.Key())
}
})
})
}

func TestKV(t *testing.T) {
Expand Down

0 comments on commit bd85c99

Please sign in to comment.