From 6bfa9f318d6341686712b65c50b76b239fa93de0 Mon Sep 17 00:00:00 2001 From: Vlad Alexandru Ionescu Date: Tue, 19 Apr 2016 21:38:32 +0100 Subject: [PATCH 1/4] Add ability to get leftmost (minimum) and rightmost (maximum) keys in treemap. --- maps/treemap/treemap.go | 10 ++++++++ maps/treemap/treemap_test.go | 34 ++++++++++++++++---------- trees/redblacktree/redblacktree.go | 38 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 6386d69..06d6185 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -73,6 +73,16 @@ func (m *Map) Get(key interface{}) (value interface{}, found bool) { return m.tree.Get(key) } +// Returns the left-most element in the tree map (minimum). +func (m *Map) Left() (key interface{}) { + return m.tree.Left() +} + +// Returns the right-most element in the tree map (maximum). +func (m *Map) Right() (key interface{}) { + return m.tree.Right() +} + // Remove the element from the map by key. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Remove(key interface{}) { diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 03fb23c..9bdfd63 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -51,13 +51,23 @@ func TestTreeMap(t *testing.T) { } // 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) + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d%d%d%d", m.Keys()...), "1234567"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // 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) + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", m.Values()...), "abcdefg"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + // test Left() + if actualValue, expectedValue := fmt.Sprintf("%d", m.Left()), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + // test Right() + if actualValue, expectedValue := fmt.Sprintf("%d", m.Right()), "7"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // key,expectedValue,expectedFound @@ -88,13 +98,13 @@ func TestTreeMap(t *testing.T) { 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) + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d", m.Keys()...), "1234"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s%s%s%s", m.Values()...), "abcd"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", m.Values()...), "abcd"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() @@ -130,13 +140,13 @@ func TestTreeMap(t *testing.T) { m.Remove(2) // Test Keys() - if actualValue, expactedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 507b8d1..67f83b2 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -186,6 +186,24 @@ func (tree *Tree) Values() []interface{} { return values } +// Returns the left-most key. +func (tree *Tree) Left() interface{} { + left := tree.leftNode() + if left == nil { + return nil + } + return left.Key +} + +// Returns the right-most key. +func (tree *Tree) Right() interface{} { + right := tree.rightNode() + if right == nil { + return nil + } + return right.Key +} + // Removes all nodes from the tree. func (tree *Tree) Clear() { tree.Root = nil @@ -232,6 +250,26 @@ func (tree *Tree) inOrder() []*Node { return nodes } +func (tree *Tree) leftNode() *Node { + var parent *Node + current := tree.Root + for current != nil { + parent = current + current = current.Left + } + return parent +} + +func (tree *Tree) rightNode() *Node { + var parent *Node + current := tree.Root + for current != nil { + parent = current + current = current.Right + } + return parent +} + func output(node *Node, prefix string, isTail bool, str *string) { if node.Right != nil { newPrefix := prefix From 160299d0f773c9211fc0d4fd3b87cbba726fd758 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Sun, 12 Jun 2016 15:04:33 +0200 Subject: [PATCH 2/4] - fix spelling mistake everywhere (expacted -> expected) and go vet/fmt --- maps/hashmap/hashmap_test.go | 24 ++++++++++++------------ sets/hashset/hashset_test.go | 4 ++-- sets/treeset/treeset_test.go | 4 ++-- trees/redblacktree/redblacktree_test.go | 24 ++++++++++++------------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/maps/hashmap/hashmap_test.go b/maps/hashmap/hashmap_test.go index 31c026b..3c28d1c 100644 --- a/maps/hashmap/hashmap_test.go +++ b/maps/hashmap/hashmap_test.go @@ -51,13 +51,13 @@ func TestHashMap(t *testing.T) { } // test Keys() - if actualValue, expactedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expactedValue) { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expactedValue) { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + 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 @@ -88,13 +88,13 @@ func TestHashMap(t *testing.T) { m.Remove(5) // test Keys() - if actualValue, expactedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expactedValue) { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expactedValue) { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() if actualValue := m.Size(); actualValue != 4 { @@ -129,13 +129,13 @@ func TestHashMap(t *testing.T) { m.Remove(2) // Test Keys() - if actualValue, expactedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() diff --git a/sets/hashset/hashset_test.go b/sets/hashset/hashset_test.go index d38006e..036f80d 100644 --- a/sets/hashset/hashset_test.go +++ b/sets/hashset/hashset_test.go @@ -70,8 +70,8 @@ func TestHashSet(t *testing.T) { set.Remove() set.Remove(1) - if actualValue, expactedValues := fmt.Sprintf("%d%d", set.Values()...), [2]string{"23", "32"}; actualValue != expactedValues[0] && actualValue != expactedValues[1] { - t.Errorf("Got %v expected %v", actualValue, expactedValues) + if actualValue, expectedValues := fmt.Sprintf("%d%d", set.Values()...), [2]string{"23", "32"}; actualValue != expectedValues[0] && actualValue != expectedValues[1] { + t.Errorf("Got %v expected %v", actualValue, expectedValues) } if actualValue := set.Contains(1); actualValue != false { diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index 4ad4265..b033a7b 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -61,8 +61,8 @@ func TestTreeSet(t *testing.T) { // repeat 10 time since map in golang has a random iteration order each time and we want to make sure that the set is ordered for i := 1; i <= 10; i++ { - if actualValue, expactedValue := fmt.Sprintf("%d%d%d", set.Values()...), "123"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%d%d%d", set.Values()...), "123"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } } diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 58fe60f..050bca5 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -51,13 +51,13 @@ func TestRedBlackTree(t *testing.T) { } // test Keys() - if actualValue, expactedValue := fmt.Sprintf("%d%d%d%d%d%d%d", tree.Keys()...), "1234567"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + 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) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s%s%s%s%s%s%s", tree.Values()...), "abcdefg"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + 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) } // key,expectedValue,expectedFound @@ -88,13 +88,13 @@ func TestRedBlackTree(t *testing.T) { tree.Remove(5) // Test Keys() - if actualValue, expactedValue := fmt.Sprintf("%d%d%d%d", tree.Keys()...), "1234"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d", tree.Keys()...), "1234"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() @@ -130,13 +130,13 @@ func TestRedBlackTree(t *testing.T) { tree.Remove(2) // Test Keys() - if actualValue, expactedValue := fmt.Sprintf("%s", tree.Keys()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Keys()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // test Values() - if actualValue, expactedValue := fmt.Sprintf("%s", tree.Values()), "[]"; actualValue != expactedValue { - t.Errorf("Got %v expected %v", actualValue, expactedValue) + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Values()), "[]"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) } // Test Size() From d13e3d6b6a9f8e541162c9ba7ede1d4ac5b687cd Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 13 Jun 2016 00:52:16 +0200 Subject: [PATCH 3/4] - Add Left(), Right(), Floor() and Ceiling() function to the red black tree with test and documentation update --- README.md | 6 ++ examples/redblacktreeextended.go | 84 ------------------- trees/redblacktree/redblacktree.go | 106 +++++++++++++++++------- trees/redblacktree/redblacktree_test.go | 56 +++++++++++++ 4 files changed, 136 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index b26838c..0d22bfa 100644 --- a/README.md +++ b/README.md @@ -471,6 +471,12 @@ func main() { tree.Clear() // empty tree.Empty() // true tree.Size() // 0 + + // Other: + tree.Left() // gets the left-most (min) node + tree.Right() // get the right-most (max) node + tree.Floor(1) // get the floor node + tree.Ceiling(1) // get the ceiling node } ``` diff --git a/examples/redblacktreeextended.go b/examples/redblacktreeextended.go index 17855c9..fbb8d6c 100644 --- a/examples/redblacktreeextended.go +++ b/examples/redblacktreeextended.go @@ -95,64 +95,6 @@ func (tree *RedBlackTreeExtended) getMaxFromNode(node *rbt.Node) (foundNode *rbt } } -// Find 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 (tree *RedBlackTreeExtended) Ceiling(key interface{}) (ceiling *rbt.Node, found bool) { - found = false - node := tree.Root - for node != nil { - compare := tree.Comparator(key, node.Key) - switch { - case compare == 0: - return node, true - case compare < 0: - ceiling, found = node, true - node = node.Left - case compare > 0: - node = node.Right - } - } - if found { - return ceiling, true - } - return nil, false -} - -// Find 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 (tree *RedBlackTreeExtended) Floor(key interface{}) (floor *rbt.Node, found bool) { - found = false - node := tree.Root - for node != nil { - compare := tree.Comparator(key, node.Key) - switch { - case compare == 0: - return node, true - case compare < 0: - node = node.Left - case compare > 0: - floor, found = node, true - node = node.Right - } - } - if found { - return floor, true - } - return nil, false -} - func print(tree *RedBlackTreeExtended) { max, _ := tree.GetMax() min, _ := tree.GetMin() @@ -190,30 +132,4 @@ func RedBlackTreeExtendedExample() { // Value for min key: c // RedBlackTree // └── 3 - - // Ceiling and Floor functions - tree = RedBlackTreeExtended{rbt.NewWithIntComparator()} - tree.Put(1, "a") - tree.Put(2, "b") - tree.Put(4, "d") - tree.Put(6, "f") - tree.Put(7, "g") - - //index, ceiling, floor - testValues := [][]interface{}{ - {0, 1, nil}, - {1, 1, 1}, - {2, 2, 2}, - {3, 4, 2}, - {4, 4, 4}, - {5, 6, 4}, - {6, 6, 6}, - {7, 7, 7}, - {8, nil, 7}, - } - for _, tt := range testValues { - actualCeiling, _ := tree.Ceiling(tt[0]) - actualFloor, _ := tree.Floor(tt[0]) - fmt.Printf("test key %d, expected (%d, %d), actual (%d, %d)\n", tt[0], tt[1], tt[2], actualCeiling.Key, actualFloor.Key) - } } diff --git a/trees/redblacktree/redblacktree.go b/trees/redblacktree/redblacktree.go index 67f83b2..2fe165b 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -186,22 +186,84 @@ func (tree *Tree) Values() []interface{} { return values } -// Returns the left-most key. -func (tree *Tree) Left() interface{} { - left := tree.leftNode() - if left == nil { - return nil +// Returns the left-most (min) node or nil if tree is empty. +func (tree *Tree) Left() *Node { + var parent *Node + current := tree.Root + for current != nil { + parent = current + current = current.Left } - return left.Key + return parent } -// Returns the right-most key. -func (tree *Tree) Right() interface{} { - right := tree.rightNode() - if right == nil { - return nil +// Returns the right-most (max) node or nil if tree is empty. +func (tree *Tree) Right() *Node { + var parent *Node + current := tree.Root + for current != nil { + parent = current + current = current.Right + } + return parent +} + +// Find 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 (tree *Tree) Floor(key interface{}) (floor *Node, found bool) { + found = false + node := tree.Root + for node != nil { + compare := tree.Comparator(key, node.Key) + switch { + case compare == 0: + return node, true + case compare < 0: + node = node.Left + case compare > 0: + floor, found = node, true + node = node.Right + } + } + if found { + return floor, true + } + return nil, false +} + +// Find 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 (tree *Tree) Ceiling(key interface{}) (ceiling *Node, found bool) { + found = false + node := tree.Root + for node != nil { + compare := tree.Comparator(key, node.Key) + switch { + case compare == 0: + return node, true + case compare < 0: + ceiling, found = node, true + node = node.Left + case compare > 0: + node = node.Right + } } - return right.Key + if found { + return ceiling, true + } + return nil, false } // Removes all nodes from the tree. @@ -250,26 +312,6 @@ func (tree *Tree) inOrder() []*Node { return nodes } -func (tree *Tree) leftNode() *Node { - var parent *Node - current := tree.Root - for current != nil { - parent = current - current = current.Left - } - return parent -} - -func (tree *Tree) rightNode() *Node { - var parent *Node - current := tree.Root - for current != nil { - parent = current - current = current.Right - } - return parent -} - func output(node *Node, prefix string, isTail bool, str *string) { if node.Right != nil { newPrefix := prefix diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 050bca5..20a287c 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -60,6 +60,38 @@ func TestRedBlackTree(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } + // test Left() + 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), "a"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + // test Right() + 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) + } + + // test Floor() + 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, "") + } + + // test Ceiling() + 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, "") + } + // key,expectedValue,expectedFound tests1 := [][]interface{}{ {1, "a", true}, @@ -97,6 +129,11 @@ func TestRedBlackTree(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } + // test Values() + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + // Test Size() if actualValue := tree.Size(); actualValue != 4 { t.Errorf("Got %v expected %v", actualValue, 7) @@ -158,6 +195,25 @@ func TestRedBlackTree(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + // test Left() + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Left()), ""; actualValue != expectedValue { + t.Errorf("Got %s expected %s", actualValue, expectedValue) + } + + // test Right() + if actualValue, expectedValue := fmt.Sprintf("%s", tree.Right()), ""; actualValue != expectedValue { + t.Errorf("Got %s expected %s", actualValue, expectedValue) + } + + // test Floor() + if node, found := tree.Floor(1); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } + + // test Ceiling() + if node, found := tree.Ceiling(1); node != nil || found { + t.Errorf("Got %v expected %v", node, "") + } } func BenchmarkRedBlackTree(b *testing.B) { From 16d751cd27416f35bc28dda7167cf9a9d987a445 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 13 Jun 2016 01:05:07 +0200 Subject: [PATCH 4/4] - Add Min() and Max() function to the tree map with test and documentation update --- README.md | 4 ++++ maps/treemap/treemap.go | 28 ++++++++++++++++++---------- maps/treemap/treemap_test.go | 21 +++++++++++++++------ 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0d22bfa..443c37d 100644 --- a/README.md +++ b/README.md @@ -400,6 +400,10 @@ func main() { m.Clear() // empty m.Empty() // true m.Size() // 0 + + // Other: + m.Min() // Returns the minimum key and its value from map. + m.Max() // Returns the maximum key and its value from map. } ``` diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index 06d6185..6d228cb 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -73,16 +73,6 @@ func (m *Map) Get(key interface{}) (value interface{}, found bool) { return m.tree.Get(key) } -// Returns the left-most element in the tree map (minimum). -func (m *Map) Left() (key interface{}) { - return m.tree.Left() -} - -// Returns the right-most element in the tree map (maximum). -func (m *Map) Right() (key interface{}) { - return m.tree.Right() -} - // Remove the element from the map by key. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Remove(key interface{}) { @@ -114,6 +104,24 @@ func (m *Map) Clear() { m.tree.Clear() } +// 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 +} + +// 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 +} + func (m *Map) String() string { str := "TreeMap\n" str += m.tree.String() diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 9bdfd63..c48c454 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -60,14 +60,14 @@ func TestTreeMap(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, expectedValue) } - // test Left() - if actualValue, expectedValue := fmt.Sprintf("%d", m.Left()), "1"; actualValue != expectedValue { - t.Errorf("Got %v expected %v", actualValue, expectedValue) + // test Min() + if key, value := m.Min(); key != 1 || value != "a" { + t.Errorf("Got %v expected %v", key, 1) } - // test Right() - if actualValue, expectedValue := fmt.Sprintf("%d", m.Right()), "7"; actualValue != expectedValue { - t.Errorf("Got %v expected %v", actualValue, expectedValue) + // test Max() + if key, value := m.Max(); key != 7 || value != "g" { + t.Errorf("Got %v expected %v", key, 7) } // key,expectedValue,expectedFound @@ -168,6 +168,15 @@ func TestTreeMap(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + // test Min() + if key, value := m.Min(); key != nil || value != nil { + t.Errorf("Got %v expected %v", key, nil) + } + + // test Max() + if key, value := m.Max(); key != nil || value != nil { + t.Errorf("Got %v expected %v", key, nil) + } } func BenchmarkTreeMap(b *testing.B) {