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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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/28] 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") From cac4f90f91a5ae02621d2613785a4e6d30a5a765 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:41:29 +0100 Subject: [PATCH 14/28] - move license of avl tree to root's license --- LICENSE | 20 +++++++++++++++++++- trees/avltree/LICENSE | 13 ------------- 2 files changed, 19 insertions(+), 14 deletions(-) delete mode 100644 trees/avltree/LICENSE diff --git a/LICENSE b/LICENSE index 89e196c..e5e449b 100644 --- a/LICENSE +++ b/LICENSE @@ -20,4 +20,22 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- + +AVL Tree: + +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/avltree/LICENSE b/trees/avltree/LICENSE deleted file mode 100644 index 985d32d..0000000 --- a/trees/avltree/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -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. From b5004c7e71414c2c7469c2db3a7c9d1584be44f5 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:48:04 +0100 Subject: [PATCH 15/28] - fix import path --- trees/avltree/avltree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index fe9cf40..f7c5457 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -13,7 +13,7 @@ import ( "log" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" + "github.com/emirpasic/gods/trees" ) func assertTreeImplementation() { From 6c67eb0b066158312d23594b2931b9bef5dacc80 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:48:18 +0100 Subject: [PATCH 16/28] - revert some of changes coming from avl tree merge --- maps/treebidimap/enumerable.go | 4 +- maps/treebidimap/iterator.go | 7 +++- maps/treebidimap/treebidimap.go | 22 +++++------ maps/treemap/enumerable.go | 9 +++-- maps/treemap/iterator.go | 7 +++- maps/treemap/treemap.go | 20 +++++----- maps/treemap/treemap_test.go | 44 ---------------------- sets/treeset/enumerable.go | 9 +++-- sets/treeset/iterator.go | 6 +-- sets/treeset/treeset.go | 13 ++----- sets/treeset/treeset_test.go | 20 ---------- trees/binaryheap/binaryheap.go | 7 ++-- trees/btree/btree.go | 32 ++-------------- trees/btree/btree_test.go | 41 +++++++++++++-------- trees/btree/iterator.go | 12 +++--- trees/redblacktree/iterator.go | 16 ++++---- trees/redblacktree/redblacktree.go | 49 +++++-------------------- trees/redblacktree/redblacktree_test.go | 41 +++++++++++++-------- trees/trees.go | 9 ----- 19 files changed, 132 insertions(+), 236 deletions(-) diff --git a/maps/treebidimap/enumerable.go b/maps/treebidimap/enumerable.go index 6ac702b..d5d829a 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 := NewWithTrees(m.forwardMap.New(), m.inverseMap.New()) + newMap := NewWith(m.keyComparator, m.valueComparator) 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 := NewWithTrees(m.forwardMap.New(), m.inverseMap.New()) + newMap := NewWith(m.keyComparator, m.valueComparator) 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 8329591..af9e27a 100644 --- a/maps/treebidimap/iterator.go +++ b/maps/treebidimap/iterator.go @@ -4,7 +4,10 @@ package treebidimap -import "github.com/emirpasic/gods/containers" +import ( + "github.com/emirpasic/gods/containers" + rbt "github.com/emirpasic/gods/trees/redblacktree" +) func assertIteratorImplementation() { var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) @@ -12,7 +15,7 @@ func assertIteratorImplementation() { // Iterator holding the iterator's state type Iterator struct { - iterator containers.ReverseIteratorWithKey + iterator rbt.Iterator } // Iterator returns a stateful iterator whose elements are key/value pairs. diff --git a/maps/treebidimap/treebidimap.go b/maps/treebidimap/treebidimap.go index 4812de6..87eff9f 100644 --- a/maps/treebidimap/treebidimap.go +++ b/maps/treebidimap/treebidimap.go @@ -19,12 +19,10 @@ package treebidimap import ( "fmt" - "strings" - "github.com/emirpasic/gods/maps" + "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" - "github.com/spewspews/gods/trees/redblacktree" + "strings" ) func assertMapImplementation() { @@ -33,8 +31,10 @@ func assertMapImplementation() { // Map holds the elements in two red-black trees. type Map struct { - forwardMap trees.Tree - inverseMap trees.Tree + forwardMap redblacktree.Tree + inverseMap redblacktree.Tree + keyComparator utils.Comparator + valueComparator utils.Comparator } type data struct { @@ -45,8 +45,10 @@ 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), + forwardMap: *redblacktree.NewWith(keyComparator), + inverseMap: *redblacktree.NewWith(valueComparator), + keyComparator: keyComparator, + valueComparator: valueComparator, } } @@ -60,10 +62,6 @@ 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/maps/treemap/enumerable.go b/maps/treemap/enumerable.go index 5f66ffb..8cea6d0 100644 --- a/maps/treemap/enumerable.go +++ b/maps/treemap/enumerable.go @@ -4,7 +4,10 @@ package treemap -import "github.com/emirpasic/gods/containers" +import ( + "github.com/emirpasic/gods/containers" + rbt "github.com/emirpasic/gods/trees/redblacktree" +) func assertEnumerableImplementation() { var _ containers.EnumerableWithKey = (*Map)(nil) @@ -21,7 +24,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: m.tree.New()} + newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)} iterator := m.Iterator() for iterator.Next() { key2, value2 := f(iterator.Key(), iterator.Value()) @@ -32,7 +35,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: m.tree.New()} + newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)} 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 3de1482..02b5c75 100644 --- a/maps/treemap/iterator.go +++ b/maps/treemap/iterator.go @@ -4,7 +4,10 @@ package treemap -import "github.com/emirpasic/gods/containers" +import ( + "github.com/emirpasic/gods/containers" + rbt "github.com/emirpasic/gods/trees/redblacktree" +) func assertIteratorImplementation() { var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) @@ -12,7 +15,7 @@ func assertIteratorImplementation() { // Iterator holding the iterator's state type Iterator struct { - iterator containers.ReverseIteratorWithKey + iterator rbt.Iterator } // Iterator returns a stateful iterator whose elements are key/value pairs. diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index bf62197..a1e58ad 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -14,8 +14,7 @@ package treemap import ( "fmt" "github.com/emirpasic/gods/maps" - rbt "github.com/spewspews/gods/trees/redblacktree" - "github.com/spewspews/gods/trees" + rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" "strings" ) @@ -26,7 +25,7 @@ func assertMapImplementation() { // Map holds the elements in a red-black tree type Map struct { - tree trees.Tree + tree *rbt.Tree } // NewWith instantiates a tree map with the custom comparator. @@ -44,11 +43,6 @@ 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{}) { @@ -96,13 +90,19 @@ 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{}) { - return m.tree.Min() + if node := m.tree.Left(); node != nil { + return node.Key, node.Value + } + return nil, nil } // 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{}) { - return m.tree.Max() + if node := m.tree.Right(); node != nil { + return node.Key, node.Value + } + return nil, nil } // String returns a string representation of container diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 4aa3e5e..0039601 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -7,8 +7,6 @@ package treemap import ( "fmt" "testing" - - "github.com/spewspews/gods/trees/avltree" ) func TestMapPut(t *testing.T) { @@ -53,48 +51,6 @@ 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/enumerable.go b/sets/treeset/enumerable.go index 9a3cb62..59a0913 100644 --- a/sets/treeset/enumerable.go +++ b/sets/treeset/enumerable.go @@ -4,7 +4,10 @@ package treeset -import "github.com/emirpasic/gods/containers" +import ( + "github.com/emirpasic/gods/containers" + rbt "github.com/emirpasic/gods/trees/redblacktree" +) func assertEnumerableImplementation() { var _ containers.EnumerableWithIndex = (*Set)(nil) @@ -21,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: set.tree.New()} + newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)} iterator := set.Iterator() for iterator.Next() { newSet.Add(f(iterator.Index(), iterator.Value())) @@ -31,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 := NewWithTree(set.tree.New()) + 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 9f76f66..2cb465f 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" + rbt "github.com/emirpasic/gods/trees/redblacktree" ) 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 containers.ReverseIteratorWithKey - tree trees.Tree + iterator rbt.Iterator + tree *rbt.Tree } // Iterator holding the iterator's state diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index ee56cc5..9ead634 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -11,12 +11,10 @@ package treeset import ( "fmt" - "strings" - "github.com/emirpasic/gods/sets" + rbt "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" - rbt "github.com/spewspews/gods/trees/redblacktree" + "strings" ) func assertSetImplementation() { @@ -25,7 +23,7 @@ func assertSetImplementation() { // Set holds elements in a red-black tree type Set struct { - tree trees.Tree + tree *rbt.Tree } var itemExists = struct{}{} @@ -45,11 +43,6 @@ func NewWithStringComparator() *Set { return &Set{tree: rbt.NewWithStringComparator()} } -// NewWithTree instantiates a new empty set with given tree -func NewWithTree(tree trees.Tree) *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 e5d5c1e..881adc2 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -7,8 +7,6 @@ package treeset import ( "fmt" "testing" - - "github.com/spewspews/gods/trees/avltree" ) func TestSetAdd(t *testing.T) { @@ -29,24 +27,6 @@ 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/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index e69d4d5..70b28cf 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -13,15 +13,14 @@ 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 _ containers.Container = (*Heap)(nil) + var _ trees.Tree = (*Heap)(nil) } // Heap holds elements in an array-list diff --git a/trees/btree/btree.go b/trees/btree/btree.go index 9ba6f5b..5f86699 100644 --- a/trees/btree/btree.go +++ b/trees/btree/btree.go @@ -19,7 +19,7 @@ package btree import ( "bytes" "fmt" - "github.com/spewspews/gods/trees" + "github.com/emirpasic/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,11 +105,6 @@ 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 @@ -172,15 +167,6 @@ 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) @@ -202,16 +188,6 @@ 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 @@ -290,7 +266,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/btree_test.go b/trees/btree/btree_test.go index 67890e6..4705bc1 100644 --- a/trees/btree/btree_test.go +++ b/trees/btree/btree_test.go @@ -929,17 +929,25 @@ 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() - i := 0 - for it.Next() { - i++ + 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()) + + 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") @@ -948,22 +956,25 @@ func TestBTreeIteratorBegin(t *testing.T) { func TestBTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator(3) - tree.Put(3, "c") - tree.Put(1, "a") - tree.Put(2, "b") it := tree.Iterator() - it.End() - - i := 0 - for it.Prev() { - i++ + 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.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") diff --git a/trees/btree/iterator.go b/trees/btree/iterator.go index c01c519..48d2496 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() containers.ReverseIteratorWithKey { - return &Iterator{tree: tree, node: nil, position: begin} +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. @@ -80,11 +80,11 @@ func (iterator *Iterator) Next() bool { } } -end: + end: iterator.End() return false -between: + between: iterator.position = between return true } @@ -139,11 +139,11 @@ func (iterator *Iterator) Prev() bool { } } -begin: + begin: iterator.Begin() return false -between: + between: iterator.position = between return true } diff --git a/trees/redblacktree/iterator.go b/trees/redblacktree/iterator.go index 56bf5a5..794e881 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() containers.ReverseIteratorWithKey { - return &Iterator{tree: tree, node: nil, position: begin} +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. @@ -55,18 +55,18 @@ 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 } } } -end: + end: iterator.node = nil iterator.position = end return false -between: + between: iterator.position = between return true } @@ -97,18 +97,18 @@ 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 } } } -begin: + begin: iterator.node = nil iterator.position = begin return false -between: + between: iterator.position = between return true } diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index aba9866..f9c9bc9 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -13,9 +13,8 @@ package redblacktree import ( "fmt" - + "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" - "github.com/spewspews/gods/trees" ) func assertTreeImplementation() { @@ -32,7 +31,7 @@ const ( type Tree struct { Root *Node size int - comparator utils.Comparator + Comparator utils.Comparator } // Node is a single element within the tree @@ -47,27 +46,17 @@ 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} -} - -// Comparator returns the comparator function for the tree. -func (tree *Tree) Comparator() utils.Comparator { - return tree.comparator -} - -// New returns a new empty tree with the same comparator. -func (tree *Tree) New() trees.Tree { - return &Tree{comparator: tree.comparator} + return &Tree{Comparator: utils.StringComparator} } // Put inserts node into the tree. @@ -80,7 +69,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 @@ -203,26 +192,6 @@ 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 (tree *Tree) Min() (interface{}, interface{}) { - n := tree.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 (tree *Tree) Max() (interface{}, interface{}) { - n := tree.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. // @@ -235,7 +204,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 @@ -264,7 +233,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 @@ -331,7 +300,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/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index f2e10b7..714defc 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -477,17 +477,25 @@ 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() - i := 0 - for it.Next() { - i++ + 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()) + + 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") @@ -496,22 +504,25 @@ func TestRedBlackTreeIteratorBegin(t *testing.T) { func TestRedBlackTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator() - tree.Put(3, "c") - tree.Put(1, "a") - tree.Put(2, "b") it := tree.Iterator() - it.End() - - i := 0 - for it.Prev() { - i++ + 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.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") diff --git a/trees/trees.go b/trees/trees.go index 4a13b83..a5a7427 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -13,15 +13,6 @@ import "github.com/emirpasic/gods/containers" // Tree interface that all trees implement type Tree interface { - New() Tree - Iterator() containers.ReverseIteratorWithKey - Put(key interface{}, value interface{}) - Remove(key interface{}) - Get(key interface{}) (interface{}, bool) - Keys() []interface{} - Min() (interface{}, interface{}) - Max() (interface{}, interface{}) - containers.Container // Empty() bool // Size() int From da92196c082ab169b7c0fb9b86ceb6f528c18309 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:49:46 +0100 Subject: [PATCH 17/28] - update read me on merge branch (leave master, author can always change the target branch to something else before merging into master) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ba27df..b2f5940 100644 --- a/README.md +++ b/README.md @@ -1255,7 +1255,7 @@ This takes a while, so test within sub-packages: Biggest contribution towards this library is to use it and give us feedback for further improvements and additions. -For direct contributions, _pull request_ into development branch or ask to become a contributor. +For direct contributions, _pull request_ into master branch or ask to become a contributor. Coding style: From dbba07eb570723f92f5f03f2a7ef3c4fde059b42 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:50:19 +0100 Subject: [PATCH 18/28] - go fmt/vet --- trees/avltree/avltree.go | 2 +- trees/btree/iterator.go | 8 ++++---- trees/redblacktree/iterator.go | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index f7c5457..0efd682 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -12,8 +12,8 @@ import ( "io/ioutil" "log" - "github.com/emirpasic/gods/utils" "github.com/emirpasic/gods/trees" + "github.com/emirpasic/gods/utils" ) func assertTreeImplementation() { diff --git a/trees/btree/iterator.go b/trees/btree/iterator.go index 48d2496..840db68 100644 --- a/trees/btree/iterator.go +++ b/trees/btree/iterator.go @@ -80,11 +80,11 @@ func (iterator *Iterator) Next() bool { } } - end: +end: iterator.End() return false - between: +between: iterator.position = between return true } @@ -139,11 +139,11 @@ func (iterator *Iterator) Prev() bool { } } - begin: +begin: iterator.Begin() return false - between: +between: iterator.position = between return true } diff --git a/trees/redblacktree/iterator.go b/trees/redblacktree/iterator.go index 794e881..90b84af 100644 --- a/trees/redblacktree/iterator.go +++ b/trees/redblacktree/iterator.go @@ -61,12 +61,12 @@ func (iterator *Iterator) Next() bool { } } - end: +end: iterator.node = nil iterator.position = end return false - between: +between: iterator.position = between return true } @@ -103,12 +103,12 @@ func (iterator *Iterator) Prev() bool { } } - begin: +begin: iterator.node = nil iterator.position = begin return false - between: +between: iterator.position = between return true } From 6f20e11a99879867fb7349069ef5e2cf7fae1685 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:54:33 +0100 Subject: [PATCH 19/28] - remove logging and panics from avl tree --- trees/avltree/avltree.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 0efd682..90ed692 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -9,9 +9,6 @@ package avltree import ( "fmt" - "io/ioutil" - "log" - "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" ) @@ -20,8 +17,6 @@ func assertTreeImplementation() { var _ trees.Tree = new(Tree) } -var dbgLog = log.New(ioutil.Discard, "avltree: ", log.LstdFlags) - // Tree holds elements of the AVL tree. type Tree struct { Root *Node @@ -304,23 +299,17 @@ func removeFix(c int8, t **Node) bool { } 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: @@ -335,12 +324,10 @@ func doublerot(c int8, s *Node) *Node { } 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] @@ -350,7 +337,6 @@ func rotate(c int8, s *Node) *Node { r.c[a^1] = s r.p = s.p s.p = r - dbgLog.Printf("rotate: exit %p:%v\n", r, r) return r } From f480e9419a65f1654567b51f273dcd5111462762 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 20:57:53 +0100 Subject: [PATCH 20/28] - simplify avl tree by exposing its comparator , i.e. del getter for comparator --- trees/avltree/avltree.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 90ed692..a0c698c 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -21,7 +21,7 @@ func assertTreeImplementation() { type Tree struct { Root *Node size int - comparator utils.Comparator + Comparator utils.Comparator } // Node is a single element within the tree @@ -35,27 +35,22 @@ 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} -} - -// Comparator returns the comparator function for the tree. -func (t *Tree) Comparator() utils.Comparator { - return t.comparator + return &Tree{Comparator: utils.StringComparator} } // New returns a new empty tree with the same comparator. func (t *Tree) New() trees.Tree { - return &Tree{comparator: t.comparator} + return &Tree{Comparator: t.Comparator} } // Size returns the number of elements stored in the tree. @@ -80,7 +75,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 @@ -105,7 +100,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 @@ -134,7 +129,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 @@ -163,7 +158,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 @@ -197,7 +192,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 { From 59734f81644071cd2890e3b789ddeda30e8f3fae Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:03:01 +0100 Subject: [PATCH 21/28] - avl tree: expose children and parent nodes, can be useful when extending structure to have access to these --- trees/avltree/avltree.go | 102 +++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index a0c698c..1116349 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -19,18 +19,18 @@ func assertTreeImplementation() { // Tree holds elements of the AVL tree. type Tree struct { - Root *Node - size int - Comparator utils.Comparator + Root *Node // Root node + Comparator utils.Comparator // Key comparator + size int // Total number of keys in the tree } // Node is a single element within the tree type Node struct { - Key interface{} - Value interface{} - c [2]*Node - p *Node - b int8 + Key interface{} + Value interface{} + Parent *Node // Parent node + Children [2]*Node // Children nodes + b int8 } // NewWith instantiates an AVL tree with the custom comparator. @@ -80,9 +80,9 @@ func (t *Tree) Get(key interface{}) (value interface{}, found bool) { case cmp == 0: return n.Value, true case cmp < 0: - n = n.c[0] + n = n.Children[0] case cmp > 0: - n = n.c[1] + n = n.Children[1] } } return nil, false @@ -105,10 +105,10 @@ func (t *Tree) Floor(key interface{}) (floor *Node, found bool) { case c == 0: return n, true case c < 0: - n = n.c[0] + n = n.Children[0] case c > 0: floor, found = n, true - n = n.c[1] + n = n.Children[1] } } if found { @@ -135,9 +135,9 @@ func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) { return n, true case c < 0: floor, found = n, true - n = n.c[0] + n = n.Children[0] case c > 0: - n = n.c[1] + n = n.Children[1] } } if found { @@ -154,7 +154,7 @@ func (t *Tree) Put(key interface{}, value interface{}) { q := *qp if q == nil { t.size++ - *qp = &Node{Key: key, Value: value, p: p} + *qp = &Node{Key: key, Value: value, Parent: p} return true } @@ -172,7 +172,7 @@ func (t *Tree) Put(key interface{}, value interface{}) { } a := (c + 1) / 2 var fix bool - fix = put(q, &q.c[a]) + fix = put(q, &q.Children[a]) if fix { return putFix(int8(c), qp) } @@ -195,14 +195,14 @@ func (t *Tree) Remove(key interface{}) { 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 + if q.Children[1] == nil { + if q.Children[0] != nil { + q.Children[0].Parent = q.Parent } - *qp = q.c[0] + *qp = q.Children[0] return true } - fix := removeMin(&q.c[1], &q.Key, &q.Value) + fix := removeMin(&q.Children[1], &q.Key, &q.Value) if fix { return removeFix(-1, qp) } @@ -215,7 +215,7 @@ func (t *Tree) Remove(key interface{}) { c = 1 } a := (c + 1) / 2 - fix := remove(&q.c[a]) + fix := remove(&q.Children[a]) if fix { return removeFix(int8(-c), qp) } @@ -227,16 +227,16 @@ func (t *Tree) Remove(key interface{}) { func removeMin(qp **Node, minKey *interface{}, minVal *interface{}) bool { q := *qp - if q.c[0] == nil { + if q.Children[0] == nil { *minKey = q.Key *minVal = q.Value - if q.c[1] != nil { - q.c[1].p = q.p + if q.Children[1] != nil { + q.Children[1].Parent = q.Parent } - *qp = q.c[1] + *qp = q.Children[1] return true } - fix := removeMin(&q.c[0], minKey, minVal) + fix := removeMin(&q.Children[0], minKey, minVal) if fix { return removeFix(1, qp) } @@ -255,7 +255,7 @@ func putFix(c int8, t **Node) bool { return false } - if s.c[(c+1)/2].b == c { + if s.Children[(c+1)/2].b == c { s = singlerot(c, s) } else { s = doublerot(c, s) @@ -277,14 +277,14 @@ func removeFix(c int8, t **Node) bool { } a := (c + 1) / 2 - if s.c[a].b == 0 { + if s.Children[a].b == 0 { s = rotate(c, s) s.b = -c *t = s return false } - if s.c[a].b == c { + if s.Children[a].b == c { s = singlerot(c, s) } else { s = doublerot(c, s) @@ -302,8 +302,8 @@ func singlerot(c int8, s *Node) *Node { func doublerot(c int8, s *Node) *Node { a := (c + 1) / 2 - r := s.c[a] - s.c[a] = rotate(-c, s.c[a]) + r := s.Children[a] + s.Children[a] = rotate(-c, s.Children[a]) p := rotate(c, s) switch { @@ -324,14 +324,14 @@ func doublerot(c int8, s *Node) *Node { func rotate(c int8, s *Node) *Node { 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 := s.Children[a] + s.Children[a] = r.Children[a^1] + if s.Children[a] != nil { + s.Children[a].Parent = s } - r.c[a^1] = s - r.p = s.p - s.p = r + r.Children[a^1] = s + r.Parent = s.Parent + s.Parent = r return r } @@ -393,7 +393,7 @@ func (t *Tree) bottom(d int) *Node { return nil } - for c := n.c[d]; c != nil; c = n.c[d] { + for c := n.Children[d]; c != nil; c = n.Children[d] { n = c } return n @@ -416,18 +416,18 @@ func (n *Node) walk1(a int) *Node { return nil } - if n.c[a] != nil { - n = n.c[a] - for n.c[a^1] != nil { - n = n.c[a^1] + if n.Children[a] != nil { + n = n.Children[a] + for n.Children[a^1] != nil { + n = n.Children[a^1] } return n } - p := n.p - for p != nil && p.c[a] == n { + p := n.Parent + for p != nil && p.Children[a] == n { n = p - p = p.p + p = p.Parent } return p } @@ -446,14 +446,14 @@ func (n *Node) String() string { } func output(node *Node, prefix string, isTail bool, str *string) { - if node.c[0] != nil { + if node.Children[0] != nil { newPrefix := prefix if isTail { newPrefix += "│ " } else { newPrefix += " " } - output(node.c[0], newPrefix, false, str) + output(node.Children[0], newPrefix, false, str) } *str += prefix if isTail { @@ -462,13 +462,13 @@ func output(node *Node, prefix string, isTail bool, str *string) { *str += "┌── " } *str += node.String() + "\n" - if node.c[1] != nil { + if node.Children[1] != nil { newPrefix := prefix if isTail { newPrefix += " " } else { newPrefix += "│ " } - output(node.c[1], newPrefix, true, str) + output(node.Children[1], newPrefix, true, str) } } From 31294e57deb707f279937caf9d429bd909bd912a Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:04:53 +0100 Subject: [PATCH 22/28] - remove copy-constructor like initialization in avl tree, could be ambiguous for clients of what the output might be. an explicit initialization with explicit comparator is a lot more obvious, more code, but more obvious. --- trees/avltree/avltree.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 1116349..d535ffc 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -48,11 +48,6 @@ func NewWithStringComparator() *Tree { return &Tree{Comparator: utils.StringComparator} } -// 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. func (t *Tree) Size() int { return t.size From d6611c11d355999f2e6cba832883be196c156f44 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:09:28 +0100 Subject: [PATCH 23/28] - getting rid of min/max from avl tree for now, until we figure out if these should be implemented on all trees (probably, yes) --- trees/avltree/avltree.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index d535ffc..cecb053 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -362,26 +362,6 @@ 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 { From 9f8722300a1673db4b176c823d32b03ba736d610 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:26:42 +0100 Subject: [PATCH 24/28] - AVL tree, remove dynamic func initialization within a func, simply extract those put/remove func on its own --- trees/avltree/avltree.go | 112 +++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index cecb053..868a0c8 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -5,6 +5,8 @@ // Package avltree implements an AVL balanced binary tree. // // Structure is not thread safe. +// +// References: https://en.wikipedia.org/wiki/AVL_tree package avltree import ( @@ -144,80 +146,78 @@ func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) { // 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, Parent: p} - return true - } + t.put(key, value, nil, &t.Root) +} - c := t.Comparator(key, q.Key) - if c == 0 { - q.Key = key - q.Value = value - return false - } +func (t *Tree) put(key interface{}, value interface{}, p *Node, qp **Node) bool { + q := *qp + if q == nil { + t.size++ + *qp = &Node{Key: key, Value: value, Parent: p} + return true + } - if c < 0 { - c = -1 - } else { - c = 1 - } - a := (c + 1) / 2 - var fix bool - fix = put(q, &q.Children[a]) - if fix { - return putFix(int8(c), qp) - } + c := t.Comparator(key, q.Key) + if c == 0 { + q.Key = key + q.Value = value return false } - put(nil, &t.Root) + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + var fix bool + fix = t.put(key, value, q, &q.Children[a]) + if fix { + return putFix(int8(c), qp) + } + return false } // 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 - } + t.remove(key, &t.Root) +} - c := t.Comparator(key, q.Key) - if c == 0 { - t.size-- - if q.Children[1] == nil { - if q.Children[0] != nil { - q.Children[0].Parent = q.Parent - } - *qp = q.Children[0] - return true - } - fix := removeMin(&q.Children[1], &q.Key, &q.Value) - if fix { - return removeFix(-1, qp) - } - return false - } +func (t *Tree) remove(key interface{}, qp **Node) bool { + q := *qp + if q == nil { + return false + } - if c < 0 { - c = -1 - } else { - c = 1 + c := t.Comparator(key, q.Key) + if c == 0 { + t.size-- + if q.Children[1] == nil { + if q.Children[0] != nil { + q.Children[0].Parent = q.Parent + } + *qp = q.Children[0] + return true } - a := (c + 1) / 2 - fix := remove(&q.Children[a]) + fix := removeMin(&q.Children[1], &q.Key, &q.Value) if fix { - return removeFix(int8(-c), qp) + return removeFix(-1, qp) } return false } - remove(&t.Root) + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + fix := t.remove(key, &q.Children[a]) + if fix { + return removeFix(int8(-c), qp) + } + return false } func removeMin(qp **Node, minKey *interface{}, minVal *interface{}) bool { From 240822f445e48bcd678e2d2e5f17fde1b3095284 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:33:07 +0100 Subject: [PATCH 25/28] - avl tree: reshuffle functions around to resemble the red-black tree ordering of functions (makes it easier to maintain code of various trees) --- trees/avltree/avltree.go | 138 +++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 868a0c8..7da52cd 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -50,20 +50,10 @@ 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 +// 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{}) { + t.put(key, value, nil, &t.Root) } // Get searches the node in the tree by key and returns its value or nil if key is not found in tree. @@ -85,6 +75,54 @@ func (t *Tree) Get(key interface{}) (value interface{}, found bool) { return nil, false } +// 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{}) { + t.remove(key, &t.Root) +} + +// Empty returns true if tree does not contain any nodes. +func (t *Tree) Empty() bool { + return t.size == 0 +} + +// Size returns the number of elements stored in the tree. +func (t *Tree) Size() int { + return t.size +} + +// 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) +} + // 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. // @@ -143,10 +181,23 @@ func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) { 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{}) { - t.put(key, value, nil, &t.Root) +// Clear removes all nodes from the tree. +func (t *Tree) Clear() { + t.Root = nil + t.size = 0 +} + +// 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 (t *Tree) put(key interface{}, value interface{}, p *Node, qp **Node) bool { @@ -178,12 +229,6 @@ func (t *Tree) put(key interface{}, value interface{}, p *Node, qp **Node) bool return false } -// 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{}) { - t.remove(key, &t.Root) -} - func (t *Tree) remove(key interface{}, qp **Node) bool { q := *qp if q == nil { @@ -330,38 +375,6 @@ func rotate(c int8, s *Node) *Node { 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 { @@ -407,19 +420,6 @@ 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.Children[0] != nil { newPrefix := prefix From bf32da08f23f313b1f6765e2ed9c1a46a0eb1d4a Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 21:47:47 +0100 Subject: [PATCH 26/28] - mimicking iterator behavior as with red-black tree (copied/pasted same test from red-black tree and fixed the iterator logic) --- trees/avltree/avltree_test.go | 42 +++++++++++++--------- trees/avltree/iterator.go | 66 +++++++++++++++++++---------------- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/trees/avltree/avltree_test.go b/trees/avltree/avltree_test.go index 2e72db3..2e791d2 100644 --- a/trees/avltree/avltree_test.go +++ b/trees/avltree/avltree_test.go @@ -1,4 +1,3 @@ -// 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. @@ -477,17 +476,25 @@ func TestAVLTreeIteratorBegin(t *testing.T) { tree.Put(2, "b") it := tree.Iterator() + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), nil) + } + it.Begin() - i := 0 - for it.Next() { - i++ + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), nil) } - if i != 3 { - t.Errorf("Got %d expected %d\n", i, tree.Size()) + + for it.Next() { } it.Begin() + + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), 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") @@ -496,22 +503,25 @@ func TestAVLTreeIteratorBegin(t *testing.T) { func TestAVLTreeIteratorEnd(t *testing.T) { tree := NewWithIntComparator() - tree.Put(3, "c") - tree.Put(1, "a") - tree.Put(2, "b") it := tree.Iterator() - it.End() - - i := 0 - for it.Prev() { - i++ + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), nil) } - if i != 3 { - t.Errorf("Got %d expected %d\n", i, tree.Size()) + + it.End() + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), nil) } + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") it.End() + if it.Key() != nil { + t.Errorf("Got %v expected %v", it.Key(), 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") diff --git a/trees/avltree/iterator.go b/trees/avltree/iterator.go index b61bc82..bf2ff14 100644 --- a/trees/avltree/iterator.go +++ b/trees/avltree/iterator.go @@ -32,17 +32,17 @@ func (tree *Tree) Iterator() containers.ReverseIteratorWithKey { // 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 { +func (iterator *Iterator) Next() bool { + switch iterator.position { case begin: - iter.position = between - iter.node = iter.tree.Left() + iterator.position = between + iterator.node = iterator.tree.Left() case between: - iter.node = iter.node.Next() + iterator.node = iterator.node.Next() } - if iter.node == nil { - iter.position = end + if iterator.node == nil { + iterator.position = end return false } return true @@ -52,17 +52,17 @@ func (iter *Iterator) Next() bool { // 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 { +func (iterator *Iterator) Prev() bool { + switch iterator.position { case end: - iter.position = between - iter.node = iter.tree.Right() + iterator.position = between + iterator.node = iterator.tree.Right() case between: - iter.node = iter.node.Prev() + iterator.node = iterator.node.Prev() } - if iter.node == nil { - iter.position = begin + if iterator.node == nil { + iterator.position = begin return false } return true @@ -70,42 +70,48 @@ func (iter *Iterator) Prev() bool { // Value returns the current element's value. // Does not modify the state of the iterator. -func (iter *Iterator) Value() interface{} { - return iter.node.Value +func (iterator *Iterator) Value() interface{} { + if iterator.node == nil { + return nil + } + return iterator.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 +func (iterator *Iterator) Key() interface{} { + if iterator.node == nil { + return nil + } + return iterator.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 +func (iterator *Iterator) Begin() { + iterator.node = nil + iterator.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 +func (iterator *Iterator) End() { + iterator.node = nil + iterator.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() +func (iterator *Iterator) First() bool { + iterator.Begin() + return iterator.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() +func (iterator *Iterator) Last() bool { + iterator.End() + return iterator.Prev() } From 42299026d89ad42e3a248642f4429c6f6ce60516 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 22:25:29 +0100 Subject: [PATCH 27/28] - flip the output of avl tree (swap left with right children in output to mimick the output given by red-black tree) --- trees/avltree/avltree.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/trees/avltree/avltree.go b/trees/avltree/avltree.go index 7da52cd..1efdae4 100644 --- a/trees/avltree/avltree.go +++ b/trees/avltree/avltree.go @@ -421,14 +421,14 @@ func (n *Node) walk1(a int) *Node { } func output(node *Node, prefix string, isTail bool, str *string) { - if node.Children[0] != nil { + if node.Children[1] != nil { newPrefix := prefix if isTail { newPrefix += "│ " } else { newPrefix += " " } - output(node.Children[0], newPrefix, false, str) + output(node.Children[1], newPrefix, false, str) } *str += prefix if isTail { @@ -437,13 +437,13 @@ func output(node *Node, prefix string, isTail bool, str *string) { *str += "┌── " } *str += node.String() + "\n" - if node.Children[1] != nil { + if node.Children[0] != nil { newPrefix := prefix if isTail { newPrefix += " " } else { newPrefix += "│ " } - output(node.Children[1], newPrefix, true, str) + output(node.Children[0], newPrefix, true, str) } } From 65ced7c4221a1772721da03cce98013e147bbe27 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 5 Mar 2017 22:31:38 +0100 Subject: [PATCH 28/28] - avl tree documentation and example --- README.md | 61 +++++++++++++++++++++++++++++++++++++++++++++ examples/avltree.go | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 examples/avltree.go diff --git a/README.md b/README.md index b2f5940..9881cee 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Implementation of various data structures and algorithms in Go. - [TreeBidiMap](#treebidimap) - [Trees](#trees) - [RedBlackTree](#redblacktree) + - [AVLTree](#avltree) - [BTree](#btree) - [BinaryHeap](#binaryheap) - [Functions](#functions) @@ -70,6 +71,7 @@ Containers are either ordered or unordered. All ordered containers provide [stat | [HashBidiMap](#hashbidimap) | no | no | no | key* | | [TreeBidiMap](#treebidimap) | yes | yes* | yes | key* | | [RedBlackTree](#redblacktree) | yes | yes* | no | key | +| [AVLTree](#avltree) | yes | yes* | no | key | | [BTree](#btree) | yes | yes* | no | key | | [BinaryHeap](#binaryheap) | yes | yes* | no | index | | | | *reversible | | *bidirectional | @@ -589,6 +591,65 @@ func main() { Extending the red-black tree's functionality has been demonstrated in the following [example](https://github.com/emirpasic/gods/blob/master/examples/redblacktreeextended.go). +#### AVLTree + +AVL [tree](#trees) is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations. + +AVL trees are often compared with red–black trees because both support the same set of operations and take O(log n) time for the basic operations. For lookup-intensive applications, AVL trees are faster than red–black trees because they are more strictly balanced. [Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) + +Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces. + +


AVL tree with balance factors (green)

+ +```go +package main + +import ( + "fmt" + avl "github.com/emirpasic/gods/trees/avltree" +) + +func main() { + tree := avl.NewWithIntComparator() // empty(keys are of type int) + + tree.Put(1, "x") // 1->x + tree.Put(2, "b") // 1->x, 2->b (in order) + tree.Put(1, "a") // 1->a, 2->b (in order, replacement) + tree.Put(3, "c") // 1->a, 2->b, 3->c (in order) + tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order) + tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order) + tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order) + + fmt.Println(tree) + // + // AVLTree + // │ ┌── 6 + // │ ┌── 5 + // └── 4 + // │ ┌── 3 + // └── 2 + // └── 1 + + + _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order) + _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order) + + tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order) + fmt.Println(tree) + // + // AVLTree + // │ ┌── 6 + // │ ┌── 5 + // └── 4 + // └── 3 + // └── 1 + + tree.Clear() // empty + tree.Empty() // true + tree.Size() // 0 +} +``` + #### BTree B-tree is a self-balancing tree data structure that keeps data sorted and allows searches, sequential access, insertions, and deletions in logarithmic time. The B-tree is a generalization of a binary search tree in that a node can have more than two children. diff --git a/examples/avltree.go b/examples/avltree.go new file mode 100644 index 0000000..bd3f96e --- /dev/null +++ b/examples/avltree.go @@ -0,0 +1,50 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package examples + +import ( + "fmt" + avl "github.com/emirpasic/gods/trees/avltree" +) + +// AVLTreeExample to demonstrate basic usage of AVLTree +func AVLTreeExample() { + tree := avl.NewWithIntComparator() // empty(keys are of type int) + + tree.Put(1, "x") // 1->x + tree.Put(2, "b") // 1->x, 2->b (in order) + tree.Put(1, "a") // 1->a, 2->b (in order, replacement) + tree.Put(3, "c") // 1->a, 2->b, 3->c (in order) + tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order) + tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order) + tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order) + + fmt.Println(tree) + // + // AVLTree + // │ ┌── 6 + // │ ┌── 5 + // └── 4 + // │ ┌── 3 + // └── 2 + // └── 1 + + _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order) + _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order) + + tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order) + fmt.Println(tree) + // + // AVLTree + // │ ┌── 6 + // │ ┌── 5 + // └── 4 + // └── 3 + // └── 1 + + tree.Clear() // empty + tree.Empty() // true + tree.Size() // 0 +}