diff --git a/README.md b/README.md index b26838c..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. } ``` @@ -471,6 +475,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/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/maps/treemap/treemap.go b/maps/treemap/treemap.go index 6386d69..6d228cb 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -104,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 03fb23c..c48c454 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 Min() + if key, value := m.Min(); key != 1 || value != "a" { + t.Errorf("Got %v expected %v", key, 1) + } + + // test Max() + if key, value := m.Max(); key != 7 || value != "g" { + t.Errorf("Got %v expected %v", key, 7) } // 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() @@ -158,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) { 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.go b/trees/redblacktree/redblacktree.go index 507b8d1..2fe165b 100644 --- a/trees/redblacktree/redblacktree.go +++ b/trees/redblacktree/redblacktree.go @@ -186,6 +186,86 @@ func (tree *Tree) Values() []interface{} { return values } +// 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 parent +} + +// 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 + } + } + if found { + return ceiling, true + } + return nil, false +} + // Removes all nodes from the tree. func (tree *Tree) Clear() { tree.Root = nil diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 58fe60f..20a287c 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -51,13 +51,45 @@ 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) + } + + // 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 @@ -88,13 +120,18 @@ 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, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; 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 +167,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() @@ -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) {