more tests, revise existing tests

pull/47/head
Benjamin Scher Purcell 9 years ago
parent e3980e5b80
commit 64f44f66bc

@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package avl implements an AVL balanced binary tree.
// Package avltree implements an AVL balanced binary tree.
//
// Structure is not thread safe.
//
package avl
package avltree
import (
"fmt"
"io/ioutil"
"log"
@ -20,7 +20,7 @@ func assertTreeImplementation() {
var _ trees.Tree = new(Tree)
}
var dbgLog = log.New(ioutil.Discard, "avl: ", log.LstdFlags)
var dbgLog = log.New(ioutil.Discard, "avltree: ", log.LstdFlags)
// Tree holds elements of the AVL tree.
type Tree struct {
@ -29,8 +29,7 @@ type Tree struct {
Comparator utils.Comparator
}
// A Node holds an Ordered element of the AVL tree in
// the Val field.
// Node is a single element within the tree
type Node struct {
Key interface{}
Value interface{}
@ -70,20 +69,18 @@ func (t *Tree) Clear() {
t.size = 0
}
// Get looks up val and returns the matching element if
// it is found.
//
// Val's Less implementation must be able to handle
// comparisons to elements stored in this tree.
// Get searches the node in the tree by key and returns its value or nil if key is not found in tree.
// Second return parameter is true if key was found, otherwise false.
// Key should adhere to the comparator's type assertion, otherwise method panics.
func (t *Tree) Get(key interface{}) (value interface{}, found bool) {
n := t.Root
for n != nil {
cmp := t.Comparator(key, n.Key)
switch {
case cmp < 0:
n = n.c[0]
case cmp == 0:
return n.Value, true
case cmp < 0:
n = n.c[0]
case cmp > 0:
n = n.c[1]
}
@ -205,7 +202,7 @@ func (t *Tree) Remove(key interface{}) {
*qp = q.c[0]
return true
}
fix := removemin(&q.c[1], &q.Key, &q.Value)
fix := removeMin(&q.c[1], &q.Key, &q.Value)
if fix {
return removeFix(-1, qp)
}
@ -228,7 +225,7 @@ func (t *Tree) Remove(key interface{}) {
remove(&t.Root)
}
func removemin(qp **Node, minKey *interface{}, minVal *interface{}) bool {
func removeMin(qp **Node, minKey *interface{}, minVal *interface{}) bool {
q := *qp
if q.c[0] == nil {
*minKey = q.Key
@ -239,7 +236,7 @@ func removemin(qp **Node, minKey *interface{}, minVal *interface{}) bool {
*qp = q.c[1]
return true
}
fix := removemin(&q.c[0], minKey, minVal)
fix := removeMin(&q.c[0], minKey, minVal)
if fix {
return removeFix(1, qp)
}
@ -423,3 +420,44 @@ func (n *Node) walk1(a int) *Node {
}
return p
}
// String returns a string representation of container
func (t *Tree) String() string {
str := "AVLTree\n"
if !t.Empty() {
output(t.Root, "", true, &str)
}
return str
}
func (n *Node) String() string {
return fmt.Sprintf("%v", n.Key)
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.c[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.c[0], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += node.String() + "\n"
if node.c[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.c[1], newPrefix, true, str)
}
}

@ -2,13 +2,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package avl
package avltree
import (
"fmt"
"math/rand"
"os"
"testing"
"time"
)
var rng *rand.Rand
func TestMain(m *testing.M) {
seed := time.Now().UTC().UnixNano()
rng = rand.New(rand.NewSource(seed))
os.Exit(m.Run())
}
func TestAVLPut(t *testing.T) {
tree := NewWithIntComparator()
tree.Put(5, "e")
@ -557,7 +568,15 @@ func TestAVLIteratorLast(t *testing.T) {
}
}
func benchmarkGet(b *testing.B, tree *Tree, size int) {
func newRandomIntTree(size, randMax int) *Tree {
tree := NewWithIntComparator()
for i := 0; i < size; i++ {
tree.Put(rng.Intn(randMax), nil)
}
return tree
}
func (tree *Tree) benchmarkGet(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Get(n)
@ -565,19 +584,53 @@ func benchmarkGet(b *testing.B, tree *Tree, size int) {
}
}
func benchmarkPut(b *testing.B, tree *Tree, size int) {
func (tree *Tree) benchmarkGetRandom(b *testing.B, size, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Get(rng.Intn(randMax))
}
}
}
func (tree *Tree) benchmarkPut(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
tree.Empty()
}
}
func (tree *Tree) benchmarkPutRandom(b *testing.B, size, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(rng.Intn(randMax), nil)
}
tree.Empty()
}
}
func benchmarkRemove(b *testing.B, tree *Tree, size int) {
func (tree *Tree) benchmarkPutAndRemove(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
for n := 0; n < size; n++ {
tree.Remove(n)
}
tree.Empty()
}
}
func (tree *Tree) benchmarkPutAndRemoveRandom(b *testing.B, size int, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(rng.Intn(randMax), nil)
}
for n := 0; n < size; n++ {
tree.Remove(rng.Intn(randMax))
}
tree.Empty()
}
}
@ -586,10 +639,10 @@ func BenchmarkAVLGet100(b *testing.B) {
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkAVLGet1000(b *testing.B) {
@ -597,10 +650,10 @@ func BenchmarkAVLGet1000(b *testing.B) {
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkAVLGet10000(b *testing.B) {
@ -608,10 +661,10 @@ func BenchmarkAVLGet10000(b *testing.B) {
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkAVLGet100000(b *testing.B) {
@ -619,18 +672,53 @@ func BenchmarkAVLGet100000(b *testing.B) {
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkAVLGetRandom100(b *testing.B) {
b.StopTimer()
size := 100
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLGetRandom1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLGetRandom10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLGetRandom100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLPut100(b *testing.B) {
b.StopTimer()
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkAVLPut1000(b *testing.B) {
@ -638,10 +726,10 @@ func BenchmarkAVLPut1000(b *testing.B) {
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkAVLPut10000(b *testing.B) {
@ -649,10 +737,10 @@ func BenchmarkAVLPut10000(b *testing.B) {
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkAVLPut100000(b *testing.B) {
@ -660,52 +748,84 @@ func BenchmarkAVLPut100000(b *testing.B) {
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkAVLPutRandom100(b *testing.B) {
b.StopTimer()
size := 100
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLRemove100(b *testing.B) {
func BenchmarkAVLPutAndRemove100(b *testing.B) {
b.StopTimer()
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkAVLRemove1000(b *testing.B) {
func BenchmarkAVLPutAndRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkAVLRemove10000(b *testing.B) {
func BenchmarkAVLPutAndRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkAVLRemove100000(b *testing.B) {
func BenchmarkAVLPutAndRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package avl
package avltree
import "github.com/emirpasic/gods/containers"

@ -6,9 +6,20 @@ package redblacktree
import (
"fmt"
"math/rand"
"os"
"testing"
"time"
)
var rng *rand.Rand
func TestMain(m *testing.M) {
seed := time.Now().UTC().UnixNano()
rng = rand.New(rand.NewSource(seed))
os.Exit(m.Run())
}
func TestRedBlackTreePut(t *testing.T) {
tree := NewWithIntComparator()
tree.Put(5, "e")
@ -19,7 +30,7 @@ func TestRedBlackTreePut(t *testing.T) {
tree.Put(1, "x")
tree.Put(2, "b")
tree.Put(1, "a") //overwrite
t.Log(tree)
if actualValue := tree.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
@ -557,7 +568,15 @@ func TestRedBlackTreeIteratorLast(t *testing.T) {
}
}
func benchmarkGet(b *testing.B, tree *Tree, size int) {
func newRandomIntTree(size, randMax int) *Tree {
tree := NewWithIntComparator()
for i := 0; i < size; i++ {
tree.Put(rng.Intn(randMax), nil)
}
return tree
}
func (tree *Tree) benchmarkGet(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Get(n)
@ -565,147 +584,248 @@ func benchmarkGet(b *testing.B, tree *Tree, size int) {
}
}
func benchmarkPut(b *testing.B, tree *Tree, size int) {
func (tree *Tree) benchmarkGetRandom(b *testing.B, size, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Get(rng.Intn(randMax))
}
}
}
func (tree *Tree) benchmarkPut(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
tree.Empty()
}
}
func (tree *Tree) benchmarkPutRandom(b *testing.B, size, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(rng.Intn(randMax), nil)
}
tree.Empty()
}
}
func benchmarkRemove(b *testing.B, tree *Tree, size int) {
func (tree *Tree) benchmarkPutAndRemove(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
for n := 0; n < size; n++ {
tree.Remove(n)
}
tree.Empty()
}
}
func (tree *Tree) benchmarkPutAndRemoveRandom(b *testing.B, size int, randMax int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
tree.Put(rng.Intn(randMax), nil)
}
for n := 0; n < size; n++ {
tree.Remove(rng.Intn(randMax))
}
tree.Empty()
}
}
func BenchmarkRedBlackTreeGet100(b *testing.B) {
func BenchmarkAVLGet100(b *testing.B) {
b.StopTimer()
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkRedBlackTreeGet1000(b *testing.B) {
func BenchmarkAVLGet1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkRedBlackTreeGet10000(b *testing.B) {
func BenchmarkAVLGet10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkRedBlackTreeGet100000(b *testing.B) {
func BenchmarkAVLGet100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkGet(b, tree, size)
tree.benchmarkGet(b, size)
}
func BenchmarkAVLGetRandom100(b *testing.B) {
b.StopTimer()
size := 100
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLGetRandom1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLGetRandom10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkRedBlackTreePut100(b *testing.B) {
func BenchmarkAVLGetRandom100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkGetRandom(b, size, size*5)
}
func BenchmarkAVLPut100(b *testing.B) {
b.StopTimer()
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkRedBlackTreePut1000(b *testing.B) {
func BenchmarkAVLPut1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkRedBlackTreePut10000(b *testing.B) {
func BenchmarkAVLPut10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkRedBlackTreePut100000(b *testing.B) {
func BenchmarkAVLPut100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkPut(b, tree, size)
tree.benchmarkPut(b, size)
}
func BenchmarkAVLPutRandom100(b *testing.B) {
b.StopTimer()
size := 100
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkAVLPutRandom100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := newRandomIntTree(size, size*5)
b.StartTimer()
tree.benchmarkPutRandom(b, size, size*5)
}
func BenchmarkRedBlackTreeRemove100(b *testing.B) {
func BenchmarkAVLPutAndRemove100(b *testing.B) {
b.StopTimer()
size := 100
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkRedBlackTreeRemove1000(b *testing.B) {
func BenchmarkAVLPutAndRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkRedBlackTreeRemove10000(b *testing.B) {
func BenchmarkAVLPutAndRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}
func BenchmarkRedBlackTreeRemove100000(b *testing.B) {
func BenchmarkAVLPutAndRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
tree := NewWithIntComparator()
for n := 0; n < size; n++ {
tree.Put(n, struct{}{})
tree.Put(n, nil)
}
b.StartTimer()
benchmarkRemove(b, tree, size)
tree.benchmarkPutAndRemove(b, size)
}

Loading…
Cancel
Save