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/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/enumerable.go b/sets/treeset/enumerable.go index 59a0913..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/emirpasic/gods/trees/redblacktree" -) +import "github.com/emirpasic/gods/containers" func assertEnumerableImplementation() { var _ containers.EnumerableWithIndex = (*Set)(nil) @@ -24,7 +21,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 +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/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..ee56cc5 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 { + 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/LICENSE b/trees/avltree/LICENSE new file mode 100644 index 0000000..985d32d --- /dev/null +++ b/trees/avltree/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/avltree/avltree.go b/trees/avltree/avltree.go new file mode 100644 index 0000000..fe9cf40 --- /dev/null +++ b/trees/avltree/avltree.go @@ -0,0 +1,493 @@ +// 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 avltree implements an AVL balanced binary tree. +// +// Structure is not thread safe. +package avltree + +import ( + "fmt" + "io/ioutil" + "log" + + "github.com/emirpasic/gods/utils" + "github.com/spewspews/gods/trees" +) + +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 + size int + comparator utils.Comparator +} + +// Node is a single element within the tree +type Node struct { + Key interface{} + Value interface{} + c [2]*Node + p *Node + b int8 +} + +// NewWith instantiates an AVL tree with the custom comparator. +func NewWith(comparator utils.Comparator) *Tree { + 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} +} + +// 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 +} + +// 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 +} + +// 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 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: + return n.Value, true + case cmp < 0: + n = n.c[0] + 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) +} + +// 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 { + 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 +} + +// 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/avltree/avltree_test.go b/trees/avltree/avltree_test.go new file mode 100644 index 0000000..2e72db3 --- /dev/null +++ b/trees/avltree/avltree_test.go @@ -0,0 +1,700 @@ +// 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 avltree + +import ( + "fmt" + "testing" +) + +func TestAVLTreePut(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 TestAVLTreeRemove(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 TestAVLTreeLeftAndRight(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 TestAVLTreeCeilingAndFloor(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 TestAVLTreeIteratorNextOnEmpty(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + for it.Next() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +func TestAVLTreeIteratorPrevOnEmpty(t *testing.T) { + tree := NewWithIntComparator() + it := tree.Iterator() + for it.Prev() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +func TestAVLTreeIterator1Next(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 TestAVLTreeIterator1Prev(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 TestAVLTreeIterator2Next(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 TestAVLTreeIterator2Prev(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 TestAVLTreeIterator3Next(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 TestAVLTreeIterator3Prev(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 TestAVLTreeIterator4Next(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 TestAVLTreeIterator4Prev(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 TestAVLTreeIteratorBegin(t *testing.T) { + tree := NewWithIntComparator() + tree.Put(3, "c") + tree.Put(1, "a") + tree.Put(2, "b") + it := tree.Iterator() + + it.Begin() + + i := 0 + for it.Next() { + i++ + } + 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") + } +} + +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 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") + } +} + +func TestAVLTreeIteratorFirst(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 TestAVLTreeIteratorLast(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 BenchmarkAVLTreeGet100(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 BenchmarkAVLTreeGet1000(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 BenchmarkAVLTreeGet10000(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 BenchmarkAVLTreeGet100000(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 BenchmarkAVLTreePut100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWithIntComparator() + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkAVLTreePut1000(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 BenchmarkAVLTreePut10000(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 BenchmarkAVLTreePut100000(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 BenchmarkAVLTreeRemove100(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 BenchmarkAVLTreeRemove1000(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 BenchmarkAVLTreeRemove10000(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 BenchmarkAVLTreeRemove100000(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/avltree/iterator.go b/trees/avltree/iterator.go new file mode 100644 index 0000000..b61bc82 --- /dev/null +++ b/trees/avltree/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 avltree + +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() 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. +// 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() +} 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/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/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. 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..aba9866 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 (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} } // 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 @@ -192,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 (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. // @@ -204,7 +235,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 +264,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 +331,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 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") diff --git a/trees/trees.go b/trees/trees.go index a5a7427..4a13b83 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -13,6 +13,15 @@ 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