From e3980e5b80c39c604c21ed7cbe56a737fd2d258e Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sat, 25 Feb 2017 14:29:26 -0600 Subject: [PATCH 01/13] add avl implementation --- trees/avl/LICENSE | 13 + trees/avl/avl.go | 425 +++++++++++++++++++++++++ trees/avl/avl_test.go | 711 ++++++++++++++++++++++++++++++++++++++++++ trees/avl/iterator.go | 111 +++++++ 4 files changed, 1260 insertions(+) create mode 100644 trees/avl/LICENSE create mode 100644 trees/avl/avl.go create mode 100644 trees/avl/avl_test.go create mode 100644 trees/avl/iterator.go diff --git a/trees/avl/LICENSE b/trees/avl/LICENSE new file mode 100644 index 0000000..985d32d --- /dev/null +++ b/trees/avl/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2017 Benjamin Scher Purcell + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/trees/avl/avl.go b/trees/avl/avl.go new file mode 100644 index 0000000..09b5181 --- /dev/null +++ b/trees/avl/avl.go @@ -0,0 +1,425 @@ +// Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved. +// 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. +// +// Structure is not thread safe. +// +package avl + +import ( + "io/ioutil" + "log" + + "github.com/emirpasic/gods/trees" + "github.com/emirpasic/gods/utils" +) + +func assertTreeImplementation() { + var _ trees.Tree = new(Tree) +} + +var dbgLog = log.New(ioutil.Discard, "avl: ", log.LstdFlags) + +// Tree holds elements of the AVL tree. +type Tree struct { + Root *Node + size int + Comparator utils.Comparator +} + +// A Node holds an Ordered element of the AVL tree in +// the Val field. +type Node struct { + Key interface{} + Value interface{} + c [2]*Node + p *Node + b int8 +} + +// NewWith instantiates a red-black tree with the custom comparator. +func NewWith(comparator utils.Comparator) *Tree { + return &Tree{Comparator: comparator} +} + +// NewWithIntComparator instantiates a red-black tree with the IntComparator, i.e. keys are of type int. +func NewWithIntComparator() *Tree { + return &Tree{Comparator: utils.IntComparator} +} + +// NewWithStringComparator instantiates a red-black tree with the StringComparator, i.e. keys are of type string. +func NewWithStringComparator() *Tree { + return &Tree{Comparator: utils.StringComparator} +} + +// Size returns the number of elements stored in the tree. +func (t *Tree) Size() int { + return t.size +} + +// Empty returns true if tree does not contain any nodes. +func (t *Tree) Empty() bool { + return t.size == 0 +} + +// Clear removes all nodes from the tree. +func (t *Tree) Clear() { + t.Root = nil + 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. +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[1] + } + } + return nil, false +} + +// Floor Finds floor node of the input key, return the floor node or nil if no ceiling is found. +// Second return parameter is true if floor was found, otherwise false. +// +// Floor node is defined as the largest node that is smaller than or equal to the given node. +// A floor node may not be found, either because the tree is empty, or because +// all nodes in the tree is larger than the given node. +// +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Floor(key interface{}) (floor *Node, found bool) { + found = false + n := t.Root + for n != nil { + c := t.Comparator(key, n.Key) + switch { + case c == 0: + return n, true + case c < 0: + n = n.c[0] + case c > 0: + floor, found = n, true + n = n.c[1] + } + } + if found { + return + } + return nil, false +} + +// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling is found. +// Second return parameter is true if ceiling was found, otherwise false. +// +// Ceiling node is defined as the smallest node that is larger than or equal to the given node. +// A ceiling node may not be found, either because the tree is empty, or because +// all nodes in the tree is smaller than the given node. +// +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) { + found = false + n := t.Root + for n != nil { + c := t.Comparator(key, n.Key) + switch { + case c == 0: + return n, true + case c < 0: + floor, found = n, true + n = n.c[0] + case c > 0: + n = n.c[1] + } + } + if found { + return + } + return nil, false +} + +// Put inserts node into the tree. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Put(key interface{}, value interface{}) { + var put func(*Node, **Node) bool + put = func(p *Node, qp **Node) bool { + q := *qp + if q == nil { + t.size++ + *qp = &Node{Key: key, Value: value, p: p} + return true + } + + c := t.Comparator(key, q.Key) + if c == 0 { + q.Key = key + q.Value = value + return false + } + + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + var fix bool + fix = put(q, &q.c[a]) + if fix { + return putFix(int8(c), qp) + } + return false + } + + put(nil, &t.Root) +} + +// Remove remove the node from the tree by key. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Remove(key interface{}) { + var remove func(**Node) bool + remove = func(qp **Node) bool { + q := *qp + if q == nil { + return false + } + + c := t.Comparator(key, q.Key) + if c == 0 { + t.size-- + if q.c[1] == nil { + if q.c[0] != nil { + q.c[0].p = q.p + } + *qp = q.c[0] + return true + } + fix := removemin(&q.c[1], &q.Key, &q.Value) + if fix { + return removeFix(-1, qp) + } + return false + } + + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + fix := remove(&q.c[a]) + if fix { + return removeFix(int8(-c), qp) + } + return false + } + + remove(&t.Root) +} + +func removemin(qp **Node, minKey *interface{}, minVal *interface{}) bool { + q := *qp + if q.c[0] == nil { + *minKey = q.Key + *minVal = q.Value + if q.c[1] != nil { + q.c[1].p = q.p + } + *qp = q.c[1] + return true + } + fix := removemin(&q.c[0], minKey, minVal) + if fix { + return removeFix(1, qp) + } + return false +} + +func putFix(c int8, t **Node) bool { + s := *t + if s.b == 0 { + s.b = c + return true + } + + if s.b == -c { + s.b = 0 + return false + } + + if s.c[(c+1)/2].b == c { + s = singlerot(c, s) + } else { + s = doublerot(c, s) + } + *t = s + return false +} + +func removeFix(c int8, t **Node) bool { + s := *t + if s.b == 0 { + s.b = c + return false + } + + if s.b == -c { + s.b = 0 + return true + } + + a := (c + 1) / 2 + if s.c[a].b == 0 { + s = rotate(c, s) + s.b = -c + *t = s + return false + } + + if s.c[a].b == c { + s = singlerot(c, s) + } else { + s = doublerot(c, s) + } + *t = s + return true +} + +func singlerot(c int8, s *Node) *Node { + dbgLog.Printf("singlerot: enter %p:%v %d\n", s, s, c) + s.b = 0 + s = rotate(c, s) + s.b = 0 + dbgLog.Printf("singlerot: exit %p:%v\n", s, s) + return s +} + +func doublerot(c int8, s *Node) *Node { + dbgLog.Printf("doublerot: enter %p:%v %d\n", s, s, c) + a := (c + 1) / 2 + r := s.c[a] + s.c[a] = rotate(-c, s.c[a]) + p := rotate(c, s) + if r.p != p || s.p != p { + panic("doublerot: bad parents") + } + + switch { + default: + s.b = 0 + r.b = 0 + case p.b == c: + s.b = -c + r.b = 0 + case p.b == -c: + s.b = 0 + r.b = c + } + + p.b = 0 + dbgLog.Printf("doublerot: exit %p:%v\n", s, s) + return p +} + +func rotate(c int8, s *Node) *Node { + dbgLog.Printf("rotate: enter %p:%v %d\n", s, s, c) + a := (c + 1) / 2 + r := s.c[a] + s.c[a] = r.c[a^1] + if s.c[a] != nil { + s.c[a].p = s + } + r.c[a^1] = s + r.p = s.p + s.p = r + dbgLog.Printf("rotate: exit %p:%v\n", r, r) + return r +} + +// Keys returns all keys in-order +func (t *Tree) Keys() []interface{} { + keys := make([]interface{}, t.size) + it := t.Iterator() + for i := 0; it.Next(); i++ { + keys[i] = it.Key() + } + return keys +} + +// Values returns all values in-order based on the key. +func (t *Tree) Values() []interface{} { + values := make([]interface{}, t.size) + it := t.Iterator() + for i := 0; it.Next(); i++ { + values[i] = it.Value() + } + return values +} + +// Left returns the minimum element of the AVL tree +// or nil if the tree is empty. +func (t *Tree) Left() *Node { + return t.bottom(0) +} + +// Right returns the maximum element of the AVL tree +// or nil if the tree is empty. +func (t *Tree) Right() *Node { + return t.bottom(1) +} + +func (t *Tree) bottom(d int) *Node { + n := t.Root + if n == nil { + return nil + } + + for c := n.c[d]; c != nil; c = n.c[d] { + n = c + } + return n +} + +// Prev returns the previous element in an inorder +// walk of the AVL tree. +func (n *Node) Prev() *Node { + return n.walk1(0) +} + +// Next returns the next element in an inorder +// walk of the AVL tree. +func (n *Node) Next() *Node { + return n.walk1(1) +} + +func (n *Node) walk1(a int) *Node { + if n == nil { + return nil + } + + if n.c[a] != nil { + n = n.c[a] + for n.c[a^1] != nil { + n = n.c[a^1] + } + return n + } + + p := n.p + for p != nil && p.c[a] == n { + n = p + p = p.p + } + return p +} diff --git a/trees/avl/avl_test.go b/trees/avl/avl_test.go new file mode 100644 index 0000000..94db9e4 --- /dev/null +++ b/trees/avl/avl_test.go @@ -0,0 +1,711 @@ +// Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package avl + +import ( + "fmt" + "testing" +) + +func TestAVLPut(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") + tree.Put(2, "b") + tree.Put(1, "a") //overwrite + + if actualValue := tree.Size(); actualValue != 7 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d%d%d%d", tree.Keys()...), "1234567"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", tree.Values()...), "abcdefg"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tests1 := [][]interface{}{ + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, nil, false}, + } + + for _, test := range tests1 { + // retrievals + actualValue, actualFound := tree.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } +} + +func TestAVLRemove(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") + tree.Put(2, "b") + tree.Put(1, "a") //overwrite + + tree.Remove(5) + tree.Remove(6) + tree.Remove(7) + tree.Remove(8) + tree.Remove(5) + + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d", tree.Keys()...), "1234"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := tree.Size(); actualValue != 4 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + + tests2 := [][]interface{}{ + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, nil, false}, + {6, nil, false}, + {7, nil, false}, + {8, nil, false}, + } + + for _, test := range tests2 { + actualValue, actualFound := tree.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } + + tree.Remove(1) + tree.Remove(4) + tree.Remove(2) + tree.Remove(3) + tree.Remove(2) + tree.Remove(2) + + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Keys()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Values()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if empty, size := tree.Empty(), tree.Size(); empty != true || size != -0 { + t.Errorf("Got %v expected %v", empty, true) + } + +} + +func TestAVLLeftAndRight(t *testing.T) { + tree := NewWithIntComparator() + + if actualValue := tree.Left(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + if actualValue := tree.Right(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + + tree.Put(1, "a") + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") // overwrite + tree.Put(2, "b") + + if actualValue, expectedValue := fmt.Sprintf("%d", tree.Left().Key), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Left().Value), "x"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + if actualValue, expectedValue := fmt.Sprintf("%d", tree.Right().Key), "7"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Right().Value), "g"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLCeilingAndFloor(t *testing.T) { + tree := NewWithIntComparator() + + if node, found := tree.Floor(0); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } + if node, found := tree.Ceiling(0); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } + + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") + tree.Put(2, "b") + + if node, found := tree.Floor(4); node.Key != 4 || !found { + t.Errorf("Got %v expected %v", node.Key, 4) + } + if node, found := tree.Floor(0); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } + + if node, found := tree.Ceiling(4); node.Key != 4 || !found { + t.Errorf("Got %v expected %v", node.Key, 4) + } + if node, found := tree.Ceiling(8); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } +} + +func TestAVLIteratorNextOnEmpty(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + for it.Next() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +func TestAVLIteratorPrevOnEmpty(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + for it.Prev() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +func TestAVLIterator1Next(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") + tree.Put(2, "b") + tree.Put(1, "a") //overwrite + // │ ┌── 7 + // └── 6 + // │ ┌── 5 + // └── 4 + // │ ┌── 3 + // └── 2 + // └── 1 + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + key := it.Key() + switch key { + case count: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator1Prev(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(5, "e") + tree.Put(6, "f") + tree.Put(7, "g") + tree.Put(3, "c") + tree.Put(4, "d") + tree.Put(1, "x") + tree.Put(2, "b") + tree.Put(1, "a") //overwrite + // │ ┌── 7 + // └── 6 + // │ ┌── 5 + // └── 4 + // │ ┌── 3 + // └── 2 + // └── 1 + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + key := it.Key() + switch key { + case countDown: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator2Next(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + key := it.Key() + switch key { + case count: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator2Prev(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + key := it.Key() + switch key { + case countDown: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator3Next(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(1, "a") + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + key := it.Key() + switch key { + case count: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator3Prev(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(1, "a") + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + key := it.Key() + switch key { + case countDown: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator4Next(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(13, 5) + tree.Put(8, 3) + tree.Put(17, 7) + tree.Put(1, 1) + tree.Put(11, 4) + tree.Put(15, 6) + tree.Put(25, 9) + tree.Put(6, 2) + tree.Put(22, 8) + tree.Put(27, 10) + // │ ┌── 27 + // │ ┌── 25 + // │ │ └── 22 + // │ ┌── 17 + // │ │ └── 15 + // └── 13 + // │ ┌── 11 + // └── 8 + // │ ┌── 6 + // └── 1 + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + value := it.Value() + switch value { + case count: + if actualValue, expectedValue := value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIterator4Prev(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(13, 5) + tree.Put(8, 3) + tree.Put(17, 7) + tree.Put(1, 1) + tree.Put(11, 4) + tree.Put(15, 6) + tree.Put(25, 9) + tree.Put(6, 2) + tree.Put(22, 8) + tree.Put(27, 10) + // │ ┌── 27 + // │ ┌── 25 + // │ │ └── 22 + // │ ┌── 17 + // │ │ └── 15 + // └── 13 + // │ ┌── 11 + // └── 8 + // │ ┌── 6 + // └── 1 + it := tree.Iterator() + count := tree.Size() + for it.Next() { + } + for it.Prev() { + value := it.Value() + switch value { + case count: + if actualValue, expectedValue := value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + count-- + } + if actualValue, expectedValue := count, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestAVLIteratorBegin(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + for it.Next() { + } + + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Next() + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + +func TestAVLIteratorEnd(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Prev() + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + +func TestAVLIteratorFirst(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 1 || value != "a" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") + } +} + +func TestAVLIteratorLast(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if key, value := it.Key(), it.Value(); key != 3 || value != "c" { + t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") + } +} + +func benchmarkGet(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Get(n) + } + } +} + +func benchmarkPut(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + } +} + +func benchmarkRemove(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Remove(n) + } + } +} + +func BenchmarkAVLGet100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkAVLGet1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkAVLGet10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkAVLGet100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkAVLPut100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWithIntComparator() + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkAVLPut1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkAVLPut10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkAVLPut100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkAVLRemove100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +func BenchmarkAVLRemove1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +func BenchmarkAVLRemove10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +func BenchmarkAVLRemove100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWithIntComparator() + for n := 0; n < size; n++ { + tree.Put(n, struct{}{}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} diff --git a/trees/avl/iterator.go b/trees/avl/iterator.go new file mode 100644 index 0000000..b2df5c6 --- /dev/null +++ b/trees/avl/iterator.go @@ -0,0 +1,111 @@ +// Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package avl + +import "github.com/emirpasic/gods/containers" + +func assertIteratorImplementation() { + var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) +} + +// Iterator holding the iterator's state +type Iterator struct { + tree *Tree + node *Node + position position +} + +type position byte + +const ( + begin, between, end position = 0, 1, 2 +) + +// Iterator returns a stateful iterator whose elements are key/value pairs. +func (tree *Tree) Iterator() Iterator { + return Iterator{tree: tree, node: nil, position: begin} +} + +// Next moves the iterator to the next element and returns true if there was a next element in the container. +// If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. +// Modifies the state of the iterator. +func (iter *Iterator) Next() bool { + switch iter.position { + case begin: + iter.position = between + iter.node = iter.tree.Left() + case between: + iter.node = iter.node.Next() + } + + if iter.node == nil { + iter.position = end + return false + } + return true +} + +// Prev moves the iterator to the next element and returns true if there was a previous element in the container. +// If Prev() returns true, then next element's key and value can be retrieved by Key() and Value(). +// If Prev() was called for the first time, then it will point the iterator to the first element if it exists. +// Modifies the state of the iterator. +func (iter *Iterator) Prev() bool { + switch iter.position { + case end: + iter.position = between + iter.node = iter.tree.Right() + case between: + iter.node = iter.node.Prev() + } + + if iter.node == nil { + iter.position = begin + return false + } + return true +} + +// Value returns the current element's value. +// Does not modify the state of the iterator. +func (iter *Iterator) Value() interface{} { + return iter.node.Value +} + +// Key returns the current element's key. +// Does not modify the state of the iterator. +func (iter *Iterator) Key() interface{} { + return iter.node.Key +} + +// Begin resets the iterator to its initial state (one-before-first) +// Call Next() to fetch the first element if any. +func (iter *Iterator) Begin() { + iter.node = nil + iter.position = begin +} + +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iter *Iterator) End() { + iter.node = nil + iter.position = end +} + +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator +func (iter *Iterator) First() bool { + iter.Begin() + return iter.Next() +} + +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator. +func (iter *Iterator) Last() bool { + iter.End() + return iter.Prev() +} From 64f44f66bce7327cad54e4700926a77b4855199e Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 13:12:51 -0600 Subject: [PATCH 02/13] more tests, revise existing tests --- trees/{avl => avltree}/LICENSE | 0 trees/{avl/avl.go => avltree/avltree.go} | 70 ++++-- .../avl_test.go => avltree/avltree_test.go} | 184 +++++++++++++--- trees/{avl => avltree}/iterator.go | 2 +- trees/redblacktree/redblacktree_test.go | 200 ++++++++++++++---- 5 files changed, 367 insertions(+), 89 deletions(-) rename trees/{avl => avltree}/LICENSE (100%) rename trees/{avl/avl.go => avltree/avltree.go} (84%) rename trees/{avl/avl_test.go => avltree/avltree_test.go} (82%) rename trees/{avl => avltree}/iterator.go (99%) diff --git a/trees/avl/LICENSE b/trees/avltree/LICENSE similarity index 100% rename from trees/avl/LICENSE rename to trees/avltree/LICENSE diff --git a/trees/avl/avl.go b/trees/avltree/avltree.go similarity index 84% rename from trees/avl/avl.go rename to trees/avltree/avltree.go index 09b5181..226efcc 100644 --- a/trees/avl/avl.go +++ b/trees/avltree/avltree.go @@ -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) + } +} diff --git a/trees/avl/avl_test.go b/trees/avltree/avltree_test.go similarity index 82% rename from trees/avl/avl_test.go rename to trees/avltree/avltree_test.go index 94db9e4..f79b739 100644 --- a/trees/avl/avl_test.go +++ b/trees/avltree/avltree_test.go @@ -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) } diff --git a/trees/avl/iterator.go b/trees/avltree/iterator.go similarity index 99% rename from trees/avl/iterator.go rename to trees/avltree/iterator.go index b2df5c6..a3d930c 100644 --- a/trees/avl/iterator.go +++ b/trees/avltree/iterator.go @@ -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" diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 714defc..bca5e7e 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -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) } From d43b189795939df57917809744f67eb607c51e71 Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 13:37:01 -0600 Subject: [PATCH 03/13] add random put and remove --- trees/avltree/avltree_test.go | 64 +++++++++++---- trees/redblacktree/redblacktree_test.go | 104 ++++++++++++++++-------- 2 files changed, 116 insertions(+), 52 deletions(-) diff --git a/trees/avltree/avltree_test.go b/trees/avltree/avltree_test.go index f79b739..a1a3e4b 100644 --- a/trees/avltree/avltree_test.go +++ b/trees/avltree/avltree_test.go @@ -681,33 +681,33 @@ func BenchmarkAVLGet100000(b *testing.B) { func BenchmarkAVLGetRandom100(b *testing.B) { b.StopTimer() size := 100 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } func BenchmarkAVLGetRandom1000(b *testing.B) { b.StopTimer() size := 1000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } func BenchmarkAVLGetRandom10000(b *testing.B) { b.StopTimer() size := 10000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } func BenchmarkAVLGetRandom100000(b *testing.B) { b.StopTimer() size := 100000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } func BenchmarkAVLPut100(b *testing.B) { @@ -757,33 +757,33 @@ func BenchmarkAVLPut100000(b *testing.B) { func BenchmarkAVLPutRandom100(b *testing.B) { b.StopTimer() size := 100 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } func BenchmarkAVLPutRandom1000(b *testing.B) { b.StopTimer() size := 1000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } func BenchmarkAVLPutRandom10000(b *testing.B) { b.StopTimer() size := 10000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } func BenchmarkAVLPutRandom100000(b *testing.B) { b.StopTimer() size := 100000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } func BenchmarkAVLPutAndRemove100(b *testing.B) { @@ -829,3 +829,35 @@ func BenchmarkAVLPutAndRemove100000(b *testing.B) { b.StartTimer() tree.benchmarkPutAndRemove(b, size) } + +func BenchmarkAVLPutAndRemoveRandom100(b *testing.B) { + b.StopTimer() + size := 100 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkAVLPutAndRemoveRandom1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkAVLPutAndRemoveRandom10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkAVLPutAndRemoveRandom100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index bca5e7e..799b56d 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -634,7 +634,7 @@ func (tree *Tree) benchmarkPutAndRemoveRandom(b *testing.B, size int, randMax in } } -func BenchmarkAVLGet100(b *testing.B) { +func BenchmarkRBTGet100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() @@ -645,7 +645,7 @@ func BenchmarkAVLGet100(b *testing.B) { tree.benchmarkGet(b, size) } -func BenchmarkAVLGet1000(b *testing.B) { +func BenchmarkRBTGet1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() @@ -656,7 +656,7 @@ func BenchmarkAVLGet1000(b *testing.B) { tree.benchmarkGet(b, size) } -func BenchmarkAVLGet10000(b *testing.B) { +func BenchmarkRBTGet10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() @@ -667,7 +667,7 @@ func BenchmarkAVLGet10000(b *testing.B) { tree.benchmarkGet(b, size) } -func BenchmarkAVLGet100000(b *testing.B) { +func BenchmarkRBTGet100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() @@ -678,39 +678,39 @@ func BenchmarkAVLGet100000(b *testing.B) { tree.benchmarkGet(b, size) } -func BenchmarkAVLGetRandom100(b *testing.B) { +func BenchmarkRBTGetRandom100(b *testing.B) { b.StopTimer() size := 100 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } -func BenchmarkAVLGetRandom1000(b *testing.B) { +func BenchmarkRBTGetRandom1000(b *testing.B) { b.StopTimer() size := 1000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } -func BenchmarkAVLGetRandom10000(b *testing.B) { +func BenchmarkRBTGetRandom10000(b *testing.B) { b.StopTimer() size := 10000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } -func BenchmarkAVLGetRandom100000(b *testing.B) { +func BenchmarkRBTGetRandom100000(b *testing.B) { b.StopTimer() size := 100000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkGetRandom(b, size, size*5) + tree.benchmarkGetRandom(b, size, size*3) } -func BenchmarkAVLPut100(b *testing.B) { +func BenchmarkRBTPut100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() @@ -721,7 +721,7 @@ func BenchmarkAVLPut100(b *testing.B) { tree.benchmarkPut(b, size) } -func BenchmarkAVLPut1000(b *testing.B) { +func BenchmarkRBTPut1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() @@ -732,7 +732,7 @@ func BenchmarkAVLPut1000(b *testing.B) { tree.benchmarkPut(b, size) } -func BenchmarkAVLPut10000(b *testing.B) { +func BenchmarkRBTPut10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() @@ -743,7 +743,7 @@ func BenchmarkAVLPut10000(b *testing.B) { tree.benchmarkPut(b, size) } -func BenchmarkAVLPut100000(b *testing.B) { +func BenchmarkRBTPut100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() @@ -754,39 +754,39 @@ func BenchmarkAVLPut100000(b *testing.B) { tree.benchmarkPut(b, size) } -func BenchmarkAVLPutRandom100(b *testing.B) { +func BenchmarkRBTPutRandom100(b *testing.B) { b.StopTimer() size := 100 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } -func BenchmarkAVLPutRandom1000(b *testing.B) { +func BenchmarkRBTPutRandom1000(b *testing.B) { b.StopTimer() size := 1000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } -func BenchmarkAVLPutRandom10000(b *testing.B) { +func BenchmarkRBTPutRandom10000(b *testing.B) { b.StopTimer() size := 10000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } -func BenchmarkAVLPutRandom100000(b *testing.B) { +func BenchmarkRBTPutRandom100000(b *testing.B) { b.StopTimer() size := 100000 - tree := newRandomIntTree(size, size*5) + tree := newRandomIntTree(size, size*3) b.StartTimer() - tree.benchmarkPutRandom(b, size, size*5) + tree.benchmarkPutRandom(b, size, size*3) } -func BenchmarkAVLPutAndRemove100(b *testing.B) { +func BenchmarkRBTPutAndRemove100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() @@ -797,7 +797,7 @@ func BenchmarkAVLPutAndRemove100(b *testing.B) { tree.benchmarkPutAndRemove(b, size) } -func BenchmarkAVLPutAndRemove1000(b *testing.B) { +func BenchmarkRBTPutAndRemove1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() @@ -808,7 +808,7 @@ func BenchmarkAVLPutAndRemove1000(b *testing.B) { tree.benchmarkPutAndRemove(b, size) } -func BenchmarkAVLPutAndRemove10000(b *testing.B) { +func BenchmarkRBTPutAndRemove10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() @@ -819,7 +819,7 @@ func BenchmarkAVLPutAndRemove10000(b *testing.B) { tree.benchmarkPutAndRemove(b, size) } -func BenchmarkAVLPutAndRemove100000(b *testing.B) { +func BenchmarkRBTPutAndRemove100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() @@ -829,3 +829,35 @@ func BenchmarkAVLPutAndRemove100000(b *testing.B) { b.StartTimer() tree.benchmarkPutAndRemove(b, size) } + +func BenchmarkRBTPutAndRemoveRandom100(b *testing.B) { + b.StopTimer() + size := 100 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkRBTPutAndRemoveRandom1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkRBTPutAndRemoveRandom10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} + +func BenchmarkRBTPutAndRemoveRandom100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := newRandomIntTree(size, size*3) + b.StartTimer() + tree.benchmarkPutAndRemoveRandom(b, size, size*3) +} From 2339521ad938d398304762c158e7290a1ebbd2f8 Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 18:49:18 -0600 Subject: [PATCH 04/13] put tests back --- trees/avltree/avltree_test.go | 266 +++++------------------- trees/redblacktree/redblacktree_test.go | 232 ++++----------------- 2 files changed, 97 insertions(+), 401 deletions(-) diff --git a/trees/avltree/avltree_test.go b/trees/avltree/avltree_test.go index a1a3e4b..7af0091 100644 --- a/trees/avltree/avltree_test.go +++ b/trees/avltree/avltree_test.go @@ -6,21 +6,10 @@ 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) { +func TestAVLTreePut(t *testing.T) { tree := NewWithIntComparator() tree.Put(5, "e") tree.Put(6, "f") @@ -61,7 +50,7 @@ func TestAVLPut(t *testing.T) { } } -func TestAVLRemove(t *testing.T) { +func TestAVLTreeRemove(t *testing.T) { tree := NewWithIntComparator() tree.Put(5, "e") tree.Put(6, "f") @@ -128,7 +117,7 @@ func TestAVLRemove(t *testing.T) { } -func TestAVLLeftAndRight(t *testing.T) { +func TestAVLTreeLeftAndRight(t *testing.T) { tree := NewWithIntComparator() if actualValue := tree.Left(); actualValue != nil { @@ -162,7 +151,7 @@ func TestAVLLeftAndRight(t *testing.T) { } } -func TestAVLCeilingAndFloor(t *testing.T) { +func TestAVLTreeCeilingAndFloor(t *testing.T) { tree := NewWithIntComparator() if node, found := tree.Floor(0); node != nil || found { @@ -195,7 +184,7 @@ func TestAVLCeilingAndFloor(t *testing.T) { } } -func TestAVLIteratorNextOnEmpty(t *testing.T) { +func TestAVLTreeIteratorNextOnEmpty(t *testing.T) { tree := NewWithIntComparator() it := tree.Iterator() for it.Next() { @@ -203,7 +192,7 @@ func TestAVLIteratorNextOnEmpty(t *testing.T) { } } -func TestAVLIteratorPrevOnEmpty(t *testing.T) { +func TestAVLTreeIteratorPrevOnEmpty(t *testing.T) { tree := NewWithIntComparator() it := tree.Iterator() for it.Prev() { @@ -211,7 +200,7 @@ func TestAVLIteratorPrevOnEmpty(t *testing.T) { } } -func TestAVLIterator1Next(t *testing.T) { +func TestAVLTreeIterator1Next(t *testing.T) { tree := NewWithIntComparator() tree.Put(5, "e") tree.Put(6, "f") @@ -249,7 +238,7 @@ func TestAVLIterator1Next(t *testing.T) { } } -func TestAVLIterator1Prev(t *testing.T) { +func TestAVLTreeIterator1Prev(t *testing.T) { tree := NewWithIntComparator() tree.Put(5, "e") tree.Put(6, "f") @@ -289,7 +278,7 @@ func TestAVLIterator1Prev(t *testing.T) { } } -func TestAVLIterator2Next(t *testing.T) { +func TestAVLTreeIterator2Next(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -315,7 +304,7 @@ func TestAVLIterator2Next(t *testing.T) { } } -func TestAVLIterator2Prev(t *testing.T) { +func TestAVLTreeIterator2Prev(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -343,7 +332,7 @@ func TestAVLIterator2Prev(t *testing.T) { } } -func TestAVLIterator3Next(t *testing.T) { +func TestAVLTreeIterator3Next(t *testing.T) { tree := NewWithIntComparator() tree.Put(1, "a") it := tree.Iterator() @@ -367,7 +356,7 @@ func TestAVLIterator3Next(t *testing.T) { } } -func TestAVLIterator3Prev(t *testing.T) { +func TestAVLTreeIterator3Prev(t *testing.T) { tree := NewWithIntComparator() tree.Put(1, "a") it := tree.Iterator() @@ -393,7 +382,7 @@ func TestAVLIterator3Prev(t *testing.T) { } } -func TestAVLIterator4Next(t *testing.T) { +func TestAVLTreeIterator4Next(t *testing.T) { tree := NewWithIntComparator() tree.Put(13, 5) tree.Put(8, 3) @@ -436,7 +425,7 @@ func TestAVLIterator4Next(t *testing.T) { } } -func TestAVLIterator4Prev(t *testing.T) { +func TestAVLTreeIterator4Prev(t *testing.T) { tree := NewWithIntComparator() tree.Put(13, 5) tree.Put(8, 3) @@ -481,7 +470,7 @@ func TestAVLIterator4Prev(t *testing.T) { } } -func TestAVLIteratorBegin(t *testing.T) { +func TestAVLTreeIteratorBegin(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -513,7 +502,7 @@ func TestAVLIteratorBegin(t *testing.T) { } } -func TestAVLIteratorEnd(t *testing.T) { +func TestAVLTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator() it := tree.Iterator() @@ -540,7 +529,7 @@ func TestAVLIteratorEnd(t *testing.T) { } } -func TestAVLIteratorFirst(t *testing.T) { +func TestAVLTreeIteratorFirst(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -554,7 +543,7 @@ func TestAVLIteratorFirst(t *testing.T) { } } -func TestAVLIteratorLast(t *testing.T) { +func TestAVLTreeIteratorLast(t *testing.T) { tree := NewWithIntComparator() tree.Put(3, "c") tree.Put(1, "a") @@ -568,15 +557,7 @@ func TestAVLIteratorLast(t *testing.T) { } } -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) { +func benchmarkGet(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { tree.Get(n) @@ -584,280 +565,147 @@ func (tree *Tree) benchmarkGet(b *testing.B, size int) { } } -func (tree *Tree) benchmarkGetRandom(b *testing.B, size, randMax int) { +func benchmarkPut(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { - tree.Get(rng.Intn(randMax)) + tree.Put(n, struct{}{}) } } } -func (tree *Tree) benchmarkPut(b *testing.B, size int) { +func benchmarkRemove(b *testing.B, tree *Tree, 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(rng.Intn(randMax), nil) - } - tree.Empty() - } -} - -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 BenchmarkAVLGet100(b *testing.B) { +func BenchmarkAVLTreeGet100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkAVLGet1000(b *testing.B) { +func BenchmarkAVLTreeGet1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkAVLGet10000(b *testing.B) { +func BenchmarkAVLTreeGet10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkAVLGet100000(b *testing.B) { +func BenchmarkAVLTreeGet100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkAVLGetRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkAVLGetRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkAVLGetRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkAVLGetRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkAVLPut100(b *testing.B) { +func BenchmarkAVLTreePut100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() - for n := 0; n < size; n++ { - tree.Put(n, nil) - } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkAVLPut1000(b *testing.B) { +func BenchmarkAVLTreePut1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkAVLPut10000(b *testing.B) { +func BenchmarkAVLTreePut10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkAVLPut100000(b *testing.B) { +func BenchmarkAVLTreePut100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkAVLPutRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkAVLPutRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkAVLPutRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkAVLPutRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkAVLPutAndRemove100(b *testing.B) { +func BenchmarkAVLTreeRemove100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkAVLPutAndRemove1000(b *testing.B) { +func BenchmarkAVLTreeRemove1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkAVLPutAndRemove10000(b *testing.B) { +func BenchmarkAVLTreeRemove10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkAVLPutAndRemove100000(b *testing.B) { +func BenchmarkAVLTreeRemove100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) -} - -func BenchmarkAVLPutAndRemoveRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkAVLPutAndRemoveRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkAVLPutAndRemoveRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkAVLPutAndRemoveRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) + benchmarkRemove(b, tree, size) } diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 799b56d..714defc 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -6,20 +6,9 @@ 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") @@ -30,7 +19,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) } @@ -568,15 +557,7 @@ func TestRedBlackTreeIteratorLast(t *testing.T) { } } -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) { +func benchmarkGet(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { tree.Get(n) @@ -584,280 +565,147 @@ func (tree *Tree) benchmarkGet(b *testing.B, size int) { } } -func (tree *Tree) benchmarkGetRandom(b *testing.B, size, randMax int) { +func benchmarkPut(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { - tree.Get(rng.Intn(randMax)) + tree.Put(n, struct{}{}) } } } -func (tree *Tree) benchmarkPut(b *testing.B, size int) { +func benchmarkRemove(b *testing.B, tree *Tree, 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(rng.Intn(randMax), nil) - } - tree.Empty() - } -} - -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 BenchmarkRBTGet100(b *testing.B) { +func BenchmarkRedBlackTreeGet100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkRBTGet1000(b *testing.B) { +func BenchmarkRedBlackTreeGet1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkRBTGet10000(b *testing.B) { +func BenchmarkRedBlackTreeGet10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) + benchmarkGet(b, tree, size) } -func BenchmarkRBTGet100000(b *testing.B) { +func BenchmarkRedBlackTreeGet100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkGet(b, size) -} - -func BenchmarkRBTGetRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkRBTGetRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkRBTGetRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) -} - -func BenchmarkRBTGetRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkGetRandom(b, size, size*3) + benchmarkGet(b, tree, size) } -func BenchmarkRBTPut100(b *testing.B) { +func BenchmarkRedBlackTreePut100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() - for n := 0; n < size; n++ { - tree.Put(n, nil) - } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkRBTPut1000(b *testing.B) { +func BenchmarkRedBlackTreePut1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkRBTPut10000(b *testing.B) { +func BenchmarkRedBlackTreePut10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) + benchmarkPut(b, tree, size) } -func BenchmarkRBTPut100000(b *testing.B) { +func BenchmarkRedBlackTreePut100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPut(b, size) -} - -func BenchmarkRBTPutRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkRBTPutRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkRBTPutRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) -} - -func BenchmarkRBTPutRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutRandom(b, size, size*3) + benchmarkPut(b, tree, size) } -func BenchmarkRBTPutAndRemove100(b *testing.B) { +func BenchmarkRedBlackTreeRemove100(b *testing.B) { b.StopTimer() size := 100 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkRBTPutAndRemove1000(b *testing.B) { +func BenchmarkRedBlackTreeRemove1000(b *testing.B) { b.StopTimer() size := 1000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkRBTPutAndRemove10000(b *testing.B) { +func BenchmarkRedBlackTreeRemove10000(b *testing.B) { b.StopTimer() size := 10000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) + benchmarkRemove(b, tree, size) } -func BenchmarkRBTPutAndRemove100000(b *testing.B) { +func BenchmarkRedBlackTreeRemove100000(b *testing.B) { b.StopTimer() size := 100000 tree := NewWithIntComparator() for n := 0; n < size; n++ { - tree.Put(n, nil) + tree.Put(n, struct{}{}) } b.StartTimer() - tree.benchmarkPutAndRemove(b, size) -} - -func BenchmarkRBTPutAndRemoveRandom100(b *testing.B) { - b.StopTimer() - size := 100 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkRBTPutAndRemoveRandom1000(b *testing.B) { - b.StopTimer() - size := 1000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkRBTPutAndRemoveRandom10000(b *testing.B) { - b.StopTimer() - size := 10000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) -} - -func BenchmarkRBTPutAndRemoveRandom100000(b *testing.B) { - b.StopTimer() - size := 100000 - tree := newRandomIntTree(size, size*3) - b.StartTimer() - tree.benchmarkPutAndRemoveRandom(b, size, size*3) + benchmarkRemove(b, tree, size) } From d84c1f0a425b940ac65527f071551dca1abe14db Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 18:52:00 -0600 Subject: [PATCH 05/13] fix documentation --- trees/avltree/avltree.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 226efcc..efcedf9 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -38,17 +38,17 @@ type Node struct { b int8 } -// NewWith instantiates a red-black tree with the custom comparator. +// NewWith instantiates an AVL tree with the custom comparator. func NewWith(comparator utils.Comparator) *Tree { return &Tree{Comparator: comparator} } -// NewWithIntComparator instantiates a red-black tree with the IntComparator, i.e. keys are of type int. +// NewWithIntComparator instantiates an AVL tree with the IntComparator, i.e. keys are of type int. func NewWithIntComparator() *Tree { return &Tree{Comparator: utils.IntComparator} } -// NewWithStringComparator instantiates a red-black tree with the StringComparator, i.e. keys are of type string. +// NewWithStringComparator instantiates an AVL tree with the StringComparator, i.e. keys are of type string. func NewWithStringComparator() *Tree { return &Tree{Comparator: utils.StringComparator} } From 67a0d2f54762a16963e4b10dba78b7ad3a77faae Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 19:46:04 -0600 Subject: [PATCH 06/13] Make treeset take an interface, make the trees satisfy that interface --- sets/treeset/enumerable.go | 6 +++--- sets/treeset/iterator.go | 6 +++--- sets/treeset/treeset.go | 13 ++++++++++--- sets/treeset/treeset_test.go | 20 ++++++++++++++++++++ trees/avltree/avltree.go | 30 ++++++++++++++++++++---------- trees/avltree/iterator.go | 4 ++-- trees/redblacktree/iterator.go | 8 ++++---- trees/redblacktree/redblacktree.go | 29 ++++++++++++++++++++--------- trees/trees.go | 13 ++++++++++++- 9 files changed, 94 insertions(+), 35 deletions(-) diff --git a/sets/treeset/enumerable.go b/sets/treeset/enumerable.go index 59a0913..db3ce9e 100644 --- a/sets/treeset/enumerable.go +++ b/sets/treeset/enumerable.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" + rbt "github.com/spewspews/gods/trees/redblacktree" ) func assertEnumerableImplementation() { @@ -24,7 +24,7 @@ func (set *Set) Each(f func(index int, value interface{})) { // Map invokes the given function once for each element and returns a // container containing the values returned by the given function. func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set { - newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)} + newSet := &Set{tree: set.tree.New()} iterator := set.Iterator() for iterator.Next() { newSet.Add(f(iterator.Index(), iterator.Value())) @@ -34,7 +34,7 @@ func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set { // Select returns a new container containing all elements for which the given function returns a true value. func (set *Set) Select(f func(index int, value interface{}) bool) *Set { - newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)} + newSet := &Set{tree: rbt.NewWith(set.tree.Comparator())} iterator := set.Iterator() for iterator.Next() { if f(iterator.Index(), iterator.Value()) { diff --git a/sets/treeset/iterator.go b/sets/treeset/iterator.go index 2cb465f..9f76f66 100644 --- a/sets/treeset/iterator.go +++ b/sets/treeset/iterator.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" + "github.com/spewspews/gods/trees" ) func assertIteratorImplementation() { @@ -16,8 +16,8 @@ func assertIteratorImplementation() { // Iterator returns a stateful iterator whose values can be fetched by an index. type Iterator struct { index int - iterator rbt.Iterator - tree *rbt.Tree + iterator containers.ReverseIteratorWithKey + tree trees.Tree } // Iterator holding the iterator's state diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 9ead634..baa168a 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -11,10 +11,12 @@ package treeset import ( "fmt" + "strings" + "github.com/emirpasic/gods/sets" - rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" - "strings" + "github.com/spewspews/gods/trees" + rbt "github.com/spewspews/gods/trees/redblacktree" ) func assertSetImplementation() { @@ -23,7 +25,7 @@ func assertSetImplementation() { // Set holds elements in a red-black tree type Set struct { - tree *rbt.Tree + tree trees.Tree } var itemExists = struct{}{} @@ -43,6 +45,11 @@ func NewWithStringComparator() *Set { return &Set{tree: rbt.NewWithStringComparator()} } +// NewWithTree instantiates a new empty set with given tree +func NewWithTree(tree trees.Tree) (set *Set) { + return &Set{tree: tree} +} + // Add adds the items (one or more) to the set. func (set *Set) Add(items ...interface{}) { for _, item := range items { diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index 881adc2..e5d5c1e 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -7,6 +7,8 @@ package treeset import ( "fmt" "testing" + + "github.com/spewspews/gods/trees/avltree" ) func TestSetAdd(t *testing.T) { @@ -27,6 +29,24 @@ func TestSetAdd(t *testing.T) { } } +func TestSetAVLAdd(t *testing.T) { + set := NewWithTree(avltree.NewWithIntComparator()) + set.Add() + set.Add(1) + set.Add(2) + set.Add(2, 3) + set.Add() + if actualValue := set.Empty(); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + if actualValue := set.Size(); actualValue != 3 { + t.Errorf("Got %v expected %v", actualValue, 3) + } + if actualValue, expectedValue := fmt.Sprintf("%d%d%d", set.Values()...), "123"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + func TestSetContains(t *testing.T) { set := NewWithIntComparator() set.Add(3, 1, 2) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index efcedf9..f446e19 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -12,8 +12,8 @@ import ( "io/ioutil" "log" - "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { @@ -26,7 +26,7 @@ var dbgLog = log.New(ioutil.Discard, "avltree: ", log.LstdFlags) type Tree struct { Root *Node size int - Comparator utils.Comparator + comparator utils.Comparator } // Node is a single element within the tree @@ -40,17 +40,27 @@ type Node struct { // NewWith instantiates an AVL tree with the custom comparator. func NewWith(comparator utils.Comparator) *Tree { - return &Tree{Comparator: comparator} + return &Tree{comparator: comparator} } // NewWithIntComparator instantiates an AVL tree with the IntComparator, i.e. keys are of type int. func NewWithIntComparator() *Tree { - return &Tree{Comparator: utils.IntComparator} + return &Tree{comparator: utils.IntComparator} } // NewWithStringComparator instantiates an AVL tree with the StringComparator, i.e. keys are of type string. func NewWithStringComparator() *Tree { - return &Tree{Comparator: utils.StringComparator} + return &Tree{comparator: utils.StringComparator} +} + +// Comparator returns the comparator function for the tree. +func (t *Tree) Comparator() utils.Comparator { + return t.comparator +} + +// New returns a new empty tree with the same comparator. +func (t *Tree) New() trees.Tree { + return &Tree{comparator: t.comparator} } // Size returns the number of elements stored in the tree. @@ -75,7 +85,7 @@ func (t *Tree) Clear() { func (t *Tree) Get(key interface{}) (value interface{}, found bool) { n := t.Root for n != nil { - cmp := t.Comparator(key, n.Key) + cmp := t.comparator(key, n.Key) switch { case cmp == 0: return n.Value, true @@ -100,7 +110,7 @@ func (t *Tree) Floor(key interface{}) (floor *Node, found bool) { found = false n := t.Root for n != nil { - c := t.Comparator(key, n.Key) + c := t.comparator(key, n.Key) switch { case c == 0: return n, true @@ -129,7 +139,7 @@ func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) { found = false n := t.Root for n != nil { - c := t.Comparator(key, n.Key) + c := t.comparator(key, n.Key) switch { case c == 0: return n, true @@ -158,7 +168,7 @@ func (t *Tree) Put(key interface{}, value interface{}) { return true } - c := t.Comparator(key, q.Key) + c := t.comparator(key, q.Key) if c == 0 { q.Key = key q.Value = value @@ -192,7 +202,7 @@ func (t *Tree) Remove(key interface{}) { return false } - c := t.Comparator(key, q.Key) + c := t.comparator(key, q.Key) if c == 0 { t.size-- if q.c[1] == nil { diff --git a/trees/avltree/iterator.go b/trees/avltree/iterator.go index a3d930c..b61bc82 100644 --- a/trees/avltree/iterator.go +++ b/trees/avltree/iterator.go @@ -24,8 +24,8 @@ const ( ) // Iterator returns a stateful iterator whose elements are key/value pairs. -func (tree *Tree) Iterator() Iterator { - return Iterator{tree: tree, node: nil, position: begin} +func (tree *Tree) Iterator() containers.ReverseIteratorWithKey { + return &Iterator{tree: tree, node: nil, position: begin} } // Next moves the iterator to the next element and returns true if there was a next element in the container. diff --git a/trees/redblacktree/iterator.go b/trees/redblacktree/iterator.go index 90b84af..56bf5a5 100644 --- a/trees/redblacktree/iterator.go +++ b/trees/redblacktree/iterator.go @@ -24,8 +24,8 @@ const ( ) // Iterator returns a stateful iterator whose elements are key/value pairs. -func (tree *Tree) Iterator() Iterator { - return Iterator{tree: tree, node: nil, position: begin} +func (tree *Tree) Iterator() containers.ReverseIteratorWithKey { + return &Iterator{tree: tree, node: nil, position: begin} } // Next moves the iterator to the next element and returns true if there was a next element in the container. @@ -55,7 +55,7 @@ func (iterator *Iterator) Next() bool { node := iterator.node for iterator.node.Parent != nil { iterator.node = iterator.node.Parent - if iterator.tree.Comparator(node.Key, iterator.node.Key) <= 0 { + if iterator.tree.comparator(node.Key, iterator.node.Key) <= 0 { goto between } } @@ -97,7 +97,7 @@ func (iterator *Iterator) Prev() bool { node := iterator.node for iterator.node.Parent != nil { iterator.node = iterator.node.Parent - if iterator.tree.Comparator(node.Key, iterator.node.Key) >= 0 { + if iterator.tree.comparator(node.Key, iterator.node.Key) >= 0 { goto between } } diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index f9c9bc9..3c39694 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -13,8 +13,9 @@ package redblacktree import ( "fmt" - "github.com/emirpasic/gods/trees" + "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { @@ -31,7 +32,7 @@ const ( type Tree struct { Root *Node size int - Comparator utils.Comparator + comparator utils.Comparator } // Node is a single element within the tree @@ -46,17 +47,27 @@ type Node struct { // NewWith instantiates a red-black tree with the custom comparator. func NewWith(comparator utils.Comparator) *Tree { - return &Tree{Comparator: comparator} + return &Tree{comparator: comparator} } // NewWithIntComparator instantiates a red-black tree with the IntComparator, i.e. keys are of type int. func NewWithIntComparator() *Tree { - return &Tree{Comparator: utils.IntComparator} + return &Tree{comparator: utils.IntComparator} } // NewWithStringComparator instantiates a red-black tree with the StringComparator, i.e. keys are of type string. func NewWithStringComparator() *Tree { - return &Tree{Comparator: utils.StringComparator} + return &Tree{comparator: utils.StringComparator} +} + +// Comparator returns the comparator function for the tree. +func (t *Tree) Comparator() utils.Comparator { + return t.comparator +} + +// New returns a new empty tree with the same comparator. +func (t *Tree) New() trees.Tree { + return &Tree{comparator: t.comparator} } // Put inserts node into the tree. @@ -69,7 +80,7 @@ func (tree *Tree) Put(key interface{}, value interface{}) { node := tree.Root loop := true for loop { - compare := tree.Comparator(key, node.Key) + compare := tree.comparator(key, node.Key) switch { case compare == 0: node.Key = key @@ -204,7 +215,7 @@ func (tree *Tree) Floor(key interface{}) (floor *Node, found bool) { found = false node := tree.Root for node != nil { - compare := tree.Comparator(key, node.Key) + compare := tree.comparator(key, node.Key) switch { case compare == 0: return node, true @@ -233,7 +244,7 @@ func (tree *Tree) Ceiling(key interface{}) (ceiling *Node, found bool) { found = false node := tree.Root for node != nil { - compare := tree.Comparator(key, node.Key) + compare := tree.comparator(key, node.Key) switch { case compare == 0: return node, true @@ -300,7 +311,7 @@ func output(node *Node, prefix string, isTail bool, str *string) { func (tree *Tree) lookup(key interface{}) *Node { node := tree.Root for node != nil { - compare := tree.Comparator(key, node.Key) + compare := tree.comparator(key, node.Key) switch { case compare == 0: return node diff --git a/trees/trees.go b/trees/trees.go index a5a7427..52b2b94 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -9,10 +9,21 @@ // Reference: https://en.wikipedia.org/wiki/Tree_%28data_structure%29 package trees -import "github.com/emirpasic/gods/containers" +import ( + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) // Tree interface that all trees implement type Tree interface { + Comparator() utils.Comparator + New() Tree + Iterator() containers.ReverseIteratorWithKey + Put(key interface{}, value interface{}) + Remove(key interface{}) + Get(key interface{}) (interface{}, bool) + Keys() []interface{} + containers.Container // Empty() bool // Size() int From 0e4eb1c32cd40c6496644e33179e67186701ae32 Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 20:10:35 -0600 Subject: [PATCH 07/13] convert treemap in the same way as treeset --- maps/treemap/enumerable.go | 9 ++---- maps/treemap/iterator.go | 7 ++--- maps/treemap/treemap.go | 20 +++++++------- maps/treemap/treemap_test.go | 44 ++++++++++++++++++++++++++++++ sets/treeset/treeset.go | 2 +- trees/avltree/avltree.go | 20 ++++++++++++++ trees/redblacktree/redblacktree.go | 20 ++++++++++++++ trees/trees.go | 2 ++ 8 files changed, 102 insertions(+), 22 deletions(-) diff --git a/maps/treemap/enumerable.go b/maps/treemap/enumerable.go index 8cea6d0..5f66ffb 100644 --- a/maps/treemap/enumerable.go +++ b/maps/treemap/enumerable.go @@ -4,10 +4,7 @@ package treemap -import ( - "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" -) +import "github.com/emirpasic/gods/containers" func assertEnumerableImplementation() { var _ containers.EnumerableWithKey = (*Map)(nil) @@ -24,7 +21,7 @@ func (m *Map) Each(f func(key interface{}, value interface{})) { // Map invokes the given function once for each element and returns a container // containing the values returned by the given function as key/value pairs. func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map { - newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)} + newMap := &Map{tree: m.tree.New()} iterator := m.Iterator() for iterator.Next() { key2, value2 := f(iterator.Key(), iterator.Value()) @@ -35,7 +32,7 @@ func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, int // Select returns a new container containing all elements for which the given function returns a true value. func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map { - newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)} + newMap := &Map{tree: m.tree.New()} iterator := m.Iterator() for iterator.Next() { if f(iterator.Key(), iterator.Value()) { diff --git a/maps/treemap/iterator.go b/maps/treemap/iterator.go index 02b5c75..3de1482 100644 --- a/maps/treemap/iterator.go +++ b/maps/treemap/iterator.go @@ -4,10 +4,7 @@ package treemap -import ( - "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" -) +import "github.com/emirpasic/gods/containers" func assertIteratorImplementation() { var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) @@ -15,7 +12,7 @@ func assertIteratorImplementation() { // Iterator holding the iterator's state type Iterator struct { - iterator rbt.Iterator + iterator containers.ReverseIteratorWithKey } // Iterator returns a stateful iterator whose elements are key/value pairs. diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index a1e58ad..bf62197 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -14,7 +14,8 @@ package treemap import ( "fmt" "github.com/emirpasic/gods/maps" - rbt "github.com/emirpasic/gods/trees/redblacktree" + rbt "github.com/spewspews/gods/trees/redblacktree" + "github.com/spewspews/gods/trees" "github.com/emirpasic/gods/utils" "strings" ) @@ -25,7 +26,7 @@ func assertMapImplementation() { // Map holds the elements in a red-black tree type Map struct { - tree *rbt.Tree + tree trees.Tree } // NewWith instantiates a tree map with the custom comparator. @@ -43,6 +44,11 @@ func NewWithStringComparator() *Map { return &Map{tree: rbt.NewWithStringComparator()} } +// NewWithTree instantiates a new empty map with given tree +func NewWithTree(tree trees.Tree) *Map { + return &Map{tree: tree} +} + // Put inserts key-value pair into the map. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Put(key interface{}, value interface{}) { @@ -90,19 +96,13 @@ func (m *Map) Clear() { // Min returns the minimum key and its value from the tree map. // Returns nil, nil if map is empty. func (m *Map) Min() (key interface{}, value interface{}) { - if node := m.tree.Left(); node != nil { - return node.Key, node.Value - } - return nil, nil + return m.tree.Min() } // Max returns the maximum key and its value from the tree map. // Returns nil, nil if map is empty. func (m *Map) Max() (key interface{}, value interface{}) { - if node := m.tree.Right(); node != nil { - return node.Key, node.Value - } - return nil, nil + return m.tree.Max() } // String returns a string representation of container diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 0039601..4aa3e5e 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -7,6 +7,8 @@ package treemap import ( "fmt" "testing" + + "github.com/spewspews/gods/trees/avltree" ) func TestMapPut(t *testing.T) { @@ -51,6 +53,48 @@ func TestMapPut(t *testing.T) { } } +func TestMapAVLPut(t *testing.T) { + m := NewWithTree(avltree.NewWithIntComparator()) + m.Put(5, "e") + m.Put(6, "f") + m.Put(7, "g") + m.Put(3, "c") + m.Put(4, "d") + m.Put(1, "x") + m.Put(2, "b") + m.Put(1, "a") //overwrite + + if actualValue := m.Size(); actualValue != 7 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + // key,expectedValue,expectedFound + tests1 := [][]interface{}{ + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, nil, false}, + } + + for _, test := range tests1 { + // retrievals + actualValue, actualFound := m.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } + +} func TestMapRemove(t *testing.T) { m := NewWithIntComparator() m.Put(5, "e") diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index baa168a..ee56cc5 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -46,7 +46,7 @@ func NewWithStringComparator() *Set { } // NewWithTree instantiates a new empty set with given tree -func NewWithTree(tree trees.Tree) (set *Set) { +func NewWithTree(tree trees.Tree) *Set { return &Set{tree: tree} } diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index f446e19..fe9cf40 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -386,6 +386,26 @@ func (t *Tree) Right() *Node { return t.bottom(1) } +// Min returns the minimum key value pair of the AVL tree +// or nils if the tree is empty. +func (t *Tree) Min() (interface{}, interface{}) { + n := t.bottom(0) + if n == nil { + return nil, nil + } + return n.Key, n.Value +} + +// Max returns the minimum key value pair of the AVL tree +// or nils if the tree is empty. +func (t *Tree) Max() (interface{}, interface{}) { + n := t.bottom(1) + if n == nil { + return nil, nil + } + return n.Key, n.Value +} + func (t *Tree) bottom(d int) *Node { n := t.Root if n == nil { diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 3c39694..611aeae 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -203,6 +203,26 @@ func (tree *Tree) Right() *Node { return parent } +// Min returns the minimum key value pair of the AVL tree +// or nils if the tree is empty. +func (t *Tree) Min() (interface{}, interface{}) { + n := t.Left() + if n == nil { + return nil, nil + } + return n.Key, n.Value +} + +// Max returns the minimum key value pair of the AVL tree +// or nils if the tree is empty. +func (t *Tree) Max() (interface{}, interface{}) { + n := t.Right() + if n == nil { + return nil, nil + } + return n.Key, n.Value +} + // Floor Finds floor node of the input key, return the floor node or nil if no ceiling is found. // Second return parameter is true if floor was found, otherwise false. // diff --git a/trees/trees.go b/trees/trees.go index 52b2b94..d79dcee 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -23,6 +23,8 @@ type Tree interface { Remove(key interface{}) Get(key interface{}) (interface{}, bool) Keys() []interface{} + Min() (interface{}, interface{}) + Max() (interface{}, interface{}) containers.Container // Empty() bool From dfbd06908b8ebf28fadd92b27a2b4a0fc3ea59bd Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 20:14:08 -0600 Subject: [PATCH 08/13] fix golint issues --- trees/redblacktree/redblacktree.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 611aeae..aba9866 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -61,13 +61,13 @@ func NewWithStringComparator() *Tree { } // Comparator returns the comparator function for the tree. -func (t *Tree) Comparator() utils.Comparator { - return t.comparator +func (tree *Tree) Comparator() utils.Comparator { + return tree.comparator } // New returns a new empty tree with the same comparator. -func (t *Tree) New() trees.Tree { - return &Tree{comparator: t.comparator} +func (tree *Tree) New() trees.Tree { + return &Tree{comparator: tree.comparator} } // Put inserts node into the tree. @@ -205,8 +205,8 @@ func (tree *Tree) Right() *Node { // Min returns the minimum key value pair of the AVL tree // or nils if the tree is empty. -func (t *Tree) Min() (interface{}, interface{}) { - n := t.Left() +func (tree *Tree) Min() (interface{}, interface{}) { + n := tree.Left() if n == nil { return nil, nil } @@ -215,8 +215,8 @@ func (t *Tree) Min() (interface{}, interface{}) { // Max returns the minimum key value pair of the AVL tree // or nils if the tree is empty. -func (t *Tree) Max() (interface{}, interface{}) { - n := t.Right() +func (tree *Tree) Max() (interface{}, interface{}) { + n := tree.Right() if n == nil { return nil, nil } From 6da2e38be569da361d6eaaa5f20e7ea023e71771 Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 20:20:24 -0600 Subject: [PATCH 09/13] fix import paths back to emirpasic --- maps/treemap/treemap.go | 4 ++-- maps/treemap/treemap_test.go | 2 +- sets/treeset/enumerable.go | 2 +- sets/treeset/iterator.go | 2 +- sets/treeset/treeset.go | 4 ++-- sets/treeset/treeset_test.go | 2 +- trees/avltree/avltree.go | 2 +- trees/redblacktree/redblacktree.go | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index bf62197..10a3a01 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -14,8 +14,8 @@ package treemap import ( "fmt" "github.com/emirpasic/gods/maps" - rbt "github.com/spewspews/gods/trees/redblacktree" - "github.com/spewspews/gods/trees" + "github.com/emirpasic/gods/trees" + rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" "strings" ) diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 4aa3e5e..1653440 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/spewspews/gods/trees/avltree" + "github.com/emirpasic/gods/trees/avltree" ) func TestMapPut(t *testing.T) { diff --git a/sets/treeset/enumerable.go b/sets/treeset/enumerable.go index db3ce9e..6f2835e 100644 --- a/sets/treeset/enumerable.go +++ b/sets/treeset/enumerable.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - rbt "github.com/spewspews/gods/trees/redblacktree" + rbt "github.com/emirpasic/gods/trees/redblacktree" ) func assertEnumerableImplementation() { diff --git a/sets/treeset/iterator.go b/sets/treeset/iterator.go index 9f76f66..64b3275 100644 --- a/sets/treeset/iterator.go +++ b/sets/treeset/iterator.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - "github.com/spewspews/gods/trees" + "github.com/emirpasic/gods/trees" ) func assertIteratorImplementation() { diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index ee56cc5..99b890d 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -14,9 +14,9 @@ import ( "strings" "github.com/emirpasic/gods/sets" + "github.com/emirpasic/gods/trees" + rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" - rbt "github.com/spewspews/gods/trees/redblacktree" ) func assertSetImplementation() { diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index e5d5c1e..d5fb3b2 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/spewspews/gods/trees/avltree" + "github.com/emirpasic/gods/trees/avltree" ) func TestSetAdd(t *testing.T) { diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index fe9cf40..0efd682 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -12,8 +12,8 @@ import ( "io/ioutil" "log" + "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index aba9866..a47e327 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -14,8 +14,8 @@ package redblacktree import ( "fmt" + "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { From 5507a9ec4d0fbadca73d938ba43b217b31e15bec Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 20:30:24 -0600 Subject: [PATCH 10/13] Revert "fix import paths back to emirpasic" The paths have to point to spewspews for the build to succeed This reverts commit 6da2e38be569da361d6eaaa5f20e7ea023e71771. --- maps/treemap/treemap.go | 4 ++-- maps/treemap/treemap_test.go | 2 +- sets/treeset/enumerable.go | 2 +- sets/treeset/iterator.go | 2 +- sets/treeset/treeset.go | 4 ++-- sets/treeset/treeset_test.go | 2 +- trees/avltree/avltree.go | 2 +- trees/redblacktree/redblacktree.go | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 10a3a01..bf62197 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -14,8 +14,8 @@ package treemap import ( "fmt" "github.com/emirpasic/gods/maps" - "github.com/emirpasic/gods/trees" - rbt "github.com/emirpasic/gods/trees/redblacktree" + rbt "github.com/spewspews/gods/trees/redblacktree" + "github.com/spewspews/gods/trees" "github.com/emirpasic/gods/utils" "strings" ) diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 1653440..4aa3e5e 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/emirpasic/gods/trees/avltree" + "github.com/spewspews/gods/trees/avltree" ) func TestMapPut(t *testing.T) { diff --git a/sets/treeset/enumerable.go b/sets/treeset/enumerable.go index 6f2835e..db3ce9e 100644 --- a/sets/treeset/enumerable.go +++ b/sets/treeset/enumerable.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" + rbt "github.com/spewspews/gods/trees/redblacktree" ) func assertEnumerableImplementation() { diff --git a/sets/treeset/iterator.go b/sets/treeset/iterator.go index 64b3275..9f76f66 100644 --- a/sets/treeset/iterator.go +++ b/sets/treeset/iterator.go @@ -6,7 +6,7 @@ package treeset import ( "github.com/emirpasic/gods/containers" - "github.com/emirpasic/gods/trees" + "github.com/spewspews/gods/trees" ) func assertIteratorImplementation() { diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 99b890d..ee56cc5 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -14,9 +14,9 @@ import ( "strings" "github.com/emirpasic/gods/sets" - "github.com/emirpasic/gods/trees" - rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" + rbt "github.com/spewspews/gods/trees/redblacktree" ) func assertSetImplementation() { diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index d5fb3b2..e5d5c1e 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/emirpasic/gods/trees/avltree" + "github.com/spewspews/gods/trees/avltree" ) func TestSetAdd(t *testing.T) { diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 0efd682..fe9cf40 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -12,8 +12,8 @@ import ( "io/ioutil" "log" - "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index a47e327..aba9866 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -14,8 +14,8 @@ package redblacktree import ( "fmt" - "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { From b8c9d1188f4f2a1478acea6653d0f09fe3284dcb Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 21:00:43 -0600 Subject: [PATCH 11/13] fix travis errors --- maps/treebidimap/enumerable.go | 4 ++-- maps/treebidimap/iterator.go | 7 ++----- maps/treebidimap/treebidimap.go | 22 ++++++++++++---------- sets/treeset/enumerable.go | 7 ++----- trees/trees.go | 6 +----- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/maps/treebidimap/enumerable.go b/maps/treebidimap/enumerable.go index d5d829a..6ac702b 100644 --- a/maps/treebidimap/enumerable.go +++ b/maps/treebidimap/enumerable.go @@ -21,7 +21,7 @@ func (m *Map) Each(f func(key interface{}, value interface{})) { // Map invokes the given function once for each element and returns a container // containing the values returned by the given function as key/value pairs. func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map { - newMap := NewWith(m.keyComparator, m.valueComparator) + newMap := NewWithTrees(m.forwardMap.New(), m.inverseMap.New()) iterator := m.Iterator() for iterator.Next() { key2, value2 := f(iterator.Key(), iterator.Value()) @@ -32,7 +32,7 @@ func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, int // Select returns a new container containing all elements for which the given function returns a true value. func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map { - newMap := NewWith(m.keyComparator, m.valueComparator) + newMap := NewWithTrees(m.forwardMap.New(), m.inverseMap.New()) iterator := m.Iterator() for iterator.Next() { if f(iterator.Key(), iterator.Value()) { diff --git a/maps/treebidimap/iterator.go b/maps/treebidimap/iterator.go index af9e27a..8329591 100644 --- a/maps/treebidimap/iterator.go +++ b/maps/treebidimap/iterator.go @@ -4,10 +4,7 @@ package treebidimap -import ( - "github.com/emirpasic/gods/containers" - rbt "github.com/emirpasic/gods/trees/redblacktree" -) +import "github.com/emirpasic/gods/containers" func assertIteratorImplementation() { var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) @@ -15,7 +12,7 @@ func assertIteratorImplementation() { // Iterator holding the iterator's state type Iterator struct { - iterator rbt.Iterator + iterator containers.ReverseIteratorWithKey } // Iterator returns a stateful iterator whose elements are key/value pairs. diff --git a/maps/treebidimap/treebidimap.go b/maps/treebidimap/treebidimap.go index 87eff9f..4812de6 100644 --- a/maps/treebidimap/treebidimap.go +++ b/maps/treebidimap/treebidimap.go @@ -19,10 +19,12 @@ package treebidimap import ( "fmt" + "strings" + "github.com/emirpasic/gods/maps" - "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" - "strings" + "github.com/spewspews/gods/trees" + "github.com/spewspews/gods/trees/redblacktree" ) func assertMapImplementation() { @@ -31,10 +33,8 @@ func assertMapImplementation() { // Map holds the elements in two red-black trees. type Map struct { - forwardMap redblacktree.Tree - inverseMap redblacktree.Tree - keyComparator utils.Comparator - valueComparator utils.Comparator + forwardMap trees.Tree + inverseMap trees.Tree } type data struct { @@ -45,10 +45,8 @@ type data struct { // NewWith instantiates a bidirectional map. func NewWith(keyComparator utils.Comparator, valueComparator utils.Comparator) *Map { return &Map{ - forwardMap: *redblacktree.NewWith(keyComparator), - inverseMap: *redblacktree.NewWith(valueComparator), - keyComparator: keyComparator, - valueComparator: valueComparator, + forwardMap: redblacktree.NewWith(keyComparator), + inverseMap: redblacktree.NewWith(valueComparator), } } @@ -62,6 +60,10 @@ func NewWithStringComparators() *Map { return NewWith(utils.StringComparator, utils.StringComparator) } +func NewWithTrees(forwardTree trees.Tree, inverseTree trees.Tree) *Map { + return &Map{forwardMap: forwardTree, inverseMap: inverseTree} +} + // Put inserts element into the map. func (m *Map) Put(key interface{}, value interface{}) { if d, ok := m.forwardMap.Get(key); ok { diff --git a/sets/treeset/enumerable.go b/sets/treeset/enumerable.go index db3ce9e..9a3cb62 100644 --- a/sets/treeset/enumerable.go +++ b/sets/treeset/enumerable.go @@ -4,10 +4,7 @@ package treeset -import ( - "github.com/emirpasic/gods/containers" - rbt "github.com/spewspews/gods/trees/redblacktree" -) +import "github.com/emirpasic/gods/containers" func assertEnumerableImplementation() { var _ containers.EnumerableWithIndex = (*Set)(nil) @@ -34,7 +31,7 @@ func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set { // Select returns a new container containing all elements for which the given function returns a true value. func (set *Set) Select(f func(index int, value interface{}) bool) *Set { - newSet := &Set{tree: rbt.NewWith(set.tree.Comparator())} + newSet := NewWithTree(set.tree.New()) iterator := set.Iterator() for iterator.Next() { if f(iterator.Index(), iterator.Value()) { diff --git a/trees/trees.go b/trees/trees.go index d79dcee..4a13b83 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -9,14 +9,10 @@ // Reference: https://en.wikipedia.org/wiki/Tree_%28data_structure%29 package trees -import ( - "github.com/emirpasic/gods/containers" - "github.com/emirpasic/gods/utils" -) +import "github.com/emirpasic/gods/containers" // Tree interface that all trees implement type Tree interface { - Comparator() utils.Comparator New() Tree Iterator() containers.ReverseIteratorWithKey Put(key interface{}, value interface{}) From c49ab09deabe9ca1a110525688f86d6be6a8d2fa Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 21:18:37 -0600 Subject: [PATCH 12/13] fix more travis issues --- trees/binaryheap/binaryheap.go | 7 ++++--- trees/btree/btree.go | 32 ++++++++++++++++++++++++++++---- trees/btree/iterator.go | 4 ++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index 70b28cf..e69d4d5 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -13,14 +13,15 @@ package binaryheap import ( "fmt" + "strings" + + "github.com/emirpasic/gods/containers" "github.com/emirpasic/gods/lists/arraylist" - "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" - "strings" ) func assertTreeImplementation() { - var _ trees.Tree = (*Heap)(nil) + var _ containers.Container = (*Heap)(nil) } // Heap holds elements in an array-list diff --git a/trees/btree/btree.go b/trees/btree/btree.go index 5f86699..9ba6f5b 100644 --- a/trees/btree/btree.go +++ b/trees/btree/btree.go @@ -19,7 +19,7 @@ package btree import ( "bytes" "fmt" - "github.com/emirpasic/gods/trees" + "github.com/spewspews/gods/trees" "github.com/emirpasic/gods/utils" "strings" ) @@ -31,7 +31,7 @@ func assertTreeImplementation() { // Tree holds elements of the B-tree type Tree struct { Root *Node // Root node - Comparator utils.Comparator // Key comparator + comparator utils.Comparator // Key comparator size int // Total number of keys in the tree m int // order (maximum number of children) } @@ -54,7 +54,7 @@ func NewWith(order int, comparator utils.Comparator) *Tree { if order < 3 { panic("Invalid order, should be at least 3") } - return &Tree{m: order, Comparator: comparator} + return &Tree{m: order, comparator: comparator} } // NewWithIntComparator instantiates a B-tree with the order (maximum number of children) and the IntComparator, i.e. keys are of type int. @@ -105,6 +105,11 @@ func (tree *Tree) Remove(key interface{}) { } } +// New returns an empty tree with the same comparator +func (tree *Tree) New() trees.Tree { + return &Tree{m: tree.m, comparator: tree.comparator} +} + // Empty returns true if tree does not contain any nodes func (tree *Tree) Empty() bool { return tree.size == 0 @@ -167,6 +172,15 @@ func (tree *Tree) LeftValue() interface{} { return nil } +// Min returns the minimum key value pair in the tree. +func (tree *Tree) Min() (interface{}, interface{}) { + n := tree.Left() + if n == nil { + return nil, nil + } + return n.Entries[0].Key, n.Entries[0].Value +} + // Right returns the right-most (max) node or nil if tree is empty. func (tree *Tree) Right() *Node { return tree.right(tree.Root) @@ -188,6 +202,16 @@ func (tree *Tree) RightValue() interface{} { return nil } +// Max returns the minimum key value pair in the tree. +func (tree *Tree) Max() (interface{}, interface{}) { + n := tree.Right() + if n == nil { + return nil, nil + } + l := len(n.Entries)-1 + return n.Entries[l].Key, n.Entries[l].Value +} + // String returns a string representation of container (for debugging purposes) func (tree *Tree) String() string { var buffer bytes.Buffer @@ -266,7 +290,7 @@ func (tree *Tree) search(node *Node, key interface{}) (index int, found bool) { var mid int for low <= high { mid = (high + low) / 2 - compare := tree.Comparator(key, node.Entries[mid].Key) + compare := tree.comparator(key, node.Entries[mid].Key) switch { case compare > 0: low = mid + 1 diff --git a/trees/btree/iterator.go b/trees/btree/iterator.go index 840db68..c01c519 100644 --- a/trees/btree/iterator.go +++ b/trees/btree/iterator.go @@ -25,8 +25,8 @@ const ( ) // Iterator returns a stateful iterator whose elements are key/value pairs. -func (tree *Tree) Iterator() Iterator { - return Iterator{tree: tree, node: nil, position: begin} +func (tree *Tree) Iterator() containers.ReverseIteratorWithKey { + return &Iterator{tree: tree, node: nil, position: begin} } // Next moves the iterator to the next element and returns true if there was a next element in the container. From 38b9436208fb039c598de76f69056b78fc2a6805 Mon Sep 17 00:00:00 2001 From: Benjamin Scher Purcell Date: Sun, 26 Feb 2017 21:45:46 -0600 Subject: [PATCH 13/13] fix tests --- trees/avltree/avltree_test.go | 41 +++++++++---------------- trees/btree/btree_test.go | 41 +++++++++---------------- trees/redblacktree/redblacktree_test.go | 41 +++++++++---------------- 3 files changed, 45 insertions(+), 78 deletions(-) diff --git a/trees/avltree/avltree_test.go b/trees/avltree/avltree_test.go index 7af0091..2e72db3 100644 --- a/trees/avltree/avltree_test.go +++ b/trees/avltree/avltree_test.go @@ -477,25 +477,17 @@ func TestAVLTreeIteratorBegin(t *testing.T) { tree.Put(2, "b") it := tree.Iterator() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - it.Begin() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - + i := 0 for it.Next() { + i++ } - - it.Begin() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.Begin() it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") @@ -504,25 +496,22 @@ func TestAVLTreeIteratorBegin(t *testing.T) { func TestAVLTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator() - it := tree.Iterator() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - - it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - tree.Put(3, "c") tree.Put(1, "a") tree.Put(2, "b") + it := tree.Iterator() + it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + + i := 0 + for it.Prev() { + i++ + } + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.End() it.Prev() if key, value := it.Key(), it.Value(); key != 3 || value != "c" { t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") diff --git a/trees/btree/btree_test.go b/trees/btree/btree_test.go index 4705bc1..67890e6 100644 --- a/trees/btree/btree_test.go +++ b/trees/btree/btree_test.go @@ -929,25 +929,17 @@ func TestBTreeIteratorBegin(t *testing.T) { tree.Put(2, "b") it := tree.Iterator() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - it.Begin() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - + i := 0 for it.Next() { + i++ } - - it.Begin() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.Begin() it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") @@ -956,25 +948,22 @@ func TestBTreeIteratorBegin(t *testing.T) { func TestBTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator(3) - it := tree.Iterator() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - - it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - tree.Put(3, "c") tree.Put(1, "a") tree.Put(2, "b") + it := tree.Iterator() + it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + + i := 0 + for it.Prev() { + i++ + } + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.End() it.Prev() if key, value := it.Key(), it.Value(); key != 3 || value != "c" { t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c") diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 714defc..f2e10b7 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -477,25 +477,17 @@ func TestRedBlackTreeIteratorBegin(t *testing.T) { tree.Put(2, "b") it := tree.Iterator() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - it.Begin() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - + i := 0 for it.Next() { + i++ } - - it.Begin() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.Begin() it.Next() if key, value := it.Key(), it.Value(); key != 1 || value != "a" { t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a") @@ -504,25 +496,22 @@ func TestRedBlackTreeIteratorBegin(t *testing.T) { func TestRedBlackTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator() - it := tree.Iterator() - - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - - it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) - } - tree.Put(3, "c") tree.Put(1, "a") tree.Put(2, "b") + it := tree.Iterator() + it.End() - if it.node != nil { - t.Errorf("Got %v expected %v", it.node, nil) + + i := 0 + for it.Prev() { + i++ + } + if i != 3 { + t.Errorf("Got %d expected %d\n", i, tree.Size()) } + it.End() it.Prev() if key, value := it.Key(), it.Value(); key != 3 || value != "c" { t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")