From 5e01f1c81f427c6d211c06a100f320ce83de9ed1 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Thu, 5 Mar 2015 18:11:14 +0100 Subject: [PATCH] treemap (inc. tests) --- maps/treemap/treemap.go | 102 +++++++++++++++++++++++ maps/treemap/treemap_test.go | 153 +++++++++++++++++++++++++++++++++++ sets/treeset/treeset.go | 2 +- 3 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 maps/treemap/treemap.go create mode 100644 maps/treemap/treemap_test.go diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go new file mode 100644 index 0000000..f659595 --- /dev/null +++ b/maps/treemap/treemap.go @@ -0,0 +1,102 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +// Implementation of order map backed by red-black tree. +// Structure is not thread safe. +// References: http://en.wikipedia.org/wiki/Associative_array + +package treemap + +import ( + "github.com/emirpasic/gods/maps" + rbt "github.com/emirpasic/gods/trees/redblacktree" + "github.com/emirpasic/gods/utils" +) + +func assertInterfaceImplementation() { + var _ maps.Interface = (*Map)(nil) +} + +type Map struct { + tree *rbt.Tree +} + +// Instantiates a tree map with the custom comparator. +func NewWith(comparator utils.Comparator) *Map { + return &Map{tree: rbt.NewWith(comparator)} +} + +// Instantiates a tree map with the IntComparator, i.e. keys are of type int. +func NewWithIntComparator() *Map { + return &Map{tree: rbt.NewWithIntComparator()} +} + +// Instantiates a tree map with the StringComparator, i.e. keys are of type string. +func NewWithStringComparator() *Map { + return &Map{tree: rbt.NewWithStringComparator()} +} + +// Inserts node into the map. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (m *Map) Put(key interface{}, value interface{}) { + m.tree.Put(key, value) +} + +// Searches the node in the map 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 (m *Map) Get(key interface{}) (value interface{}, found bool) { + return m.tree.Get(key) +} + +// Remove the node from the map by key. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (m *Map) Remove(key interface{}) { + m.tree.Remove(key) +} + +// Returns true if map does not contain any nodes +func (m *Map) Empty() bool { + return m.tree.Empty() +} + +// Returns number of items in the map. +func (m *Map) Size() int { + return m.tree.Size() +} + +// Returns all keys in-order +func (m *Map) Keys() []interface{} { + return m.tree.Keys() +} + +// Returns all values in-order based on the key. +func (m *Map) Values() []interface{} { + return m.tree.Values() +} + +// Removes all nodes from the map. +func (m *Map) Clear() { + m.tree.Clear() +} + +func (m *Map) String() string { + str := "TreeMap\n" + str += m.tree.String() + return str +} diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go new file mode 100644 index 0000000..83c6809 --- /dev/null +++ b/maps/treemap/treemap_test.go @@ -0,0 +1,153 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +package treemap + +import ( + "fmt" + "testing" +) + +func TestRedBlackTree(t *testing.T) { + + m := NewWithIntComparator() + + // insertions + 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 + + // Test Size() + if actualValue := m.Size(); actualValue != 7 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + + // test Keys() + if actualValue, expactedValue := fmt.Sprintf("%d%d%d%d%d%d%d", m.Keys()...), "1234567"; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := fmt.Sprintf("%s%s%s%s%s%s%s", m.Values()...), "abcdefg"; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // 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]) + } + } + + // removals + m.Remove(5) + m.Remove(6) + m.Remove(7) + m.Remove(8) + m.Remove(5) + + // Test Keys() + if actualValue, expactedValue := fmt.Sprintf("%d%d%d%d", m.Keys()...), "1234"; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := fmt.Sprintf("%s%s%s%s", m.Values()...), "abcd"; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // Test Size() + if actualValue := m.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 { + // retrievals + actualValue, actualFound := m.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } + + // removals + m.Remove(1) + m.Remove(4) + m.Remove(2) + m.Remove(3) + m.Remove(2) + m.Remove(2) + + // Test Keys() + if actualValue, expactedValue := fmt.Sprintf("", m.Keys()...), ""; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := fmt.Sprintf("", m.Values()...), ""; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // Test Size() + if actualValue := m.Size(); actualValue != 0 { + t.Errorf("Got %v expected %v", actualValue, 0) + } + + // Test Empty() + if actualValue := m.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + m.Put(1, "a") + m.Put(2, "b") + m.Clear() + + // Test Empty() + if actualValue := m.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + +} diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go index 6e50120..9236eb1 100644 --- a/sets/treeset/treeset.go +++ b/sets/treeset/treeset.go @@ -50,7 +50,7 @@ func NewWithIntComparator() *Set { return &Set{tree: rbt.NewWithIntComparator()} } -// Instantiates a new empty sete with the StringComparator, i.e. keys are of type string. +// Instantiates a new empty set with the StringComparator, i.e. keys are of type string. func NewWithStringComparator() *Set { return &Set{tree: rbt.NewWithStringComparator()} }