From 187c76e5a4856d0804e58a869c9aa18d69566789 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Thu, 5 Mar 2015 17:44:00 +0100 Subject: [PATCH] implemented tree set (inc. tests) --- sets/treeset/treeset.go | 112 +++++++++++++++++++++++++++++++++++ sets/treeset/treeset_test.go | 86 +++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 sets/treeset/treeset.go create mode 100644 sets/treeset/treeset_test.go diff --git a/sets/treeset/treeset.go b/sets/treeset/treeset.go new file mode 100644 index 0000000..6e50120 --- /dev/null +++ b/sets/treeset/treeset.go @@ -0,0 +1,112 @@ +/* +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 an ordered set backed by a red-black tree. +// Structure is not thread safe. +// References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 + +package treeset + +import ( + "fmt" + "github.com/emirpasic/gods/sets" + rbt "github.com/emirpasic/gods/trees/redblacktree" + "github.com/emirpasic/gods/utils" + "strings" +) + +func assertInterfaceImplementation() { + var _ sets.Interface = (*Set)(nil) +} + +type Set struct { + tree *rbt.Tree +} + +var itemExists = struct{}{} + +// Instantiates a new empty set with the custom comparator. +func NewWith(comparator utils.Comparator) *Set { + return &Set{tree: rbt.NewWith(comparator)} +} + +// Instantiates a new empty set with the IntComparator, i.e. keys are of type int. +func NewWithIntComparator() *Set { + return &Set{tree: rbt.NewWithIntComparator()} +} + +// Instantiates a new empty sete with the StringComparator, i.e. keys are of type string. +func NewWithStringComparator() *Set { + return &Set{tree: rbt.NewWithStringComparator()} +} + +// Adds the items (one or more) to the set. +func (set *Set) Add(items ...interface{}) { + for _, item := range items { + set.tree.Put(item, itemExists) + } +} + +// Removes the items (one or more) from the set. +func (set *Set) Remove(items ...interface{}) { + for _, item := range items { + set.tree.Remove(item) + } +} + +// Check wether items (one or more) are present in the set. +// All items have to be present in the set for the method to return true. +// Returns true if no arguments are passed at all, i.e. set is always superset of empty set. +func (set *Set) Contains(items ...interface{}) bool { + for _, item := range items { + if _, contains := set.tree.Get(item); !contains { + return false + } + } + return true +} + +// Returns true if set does not contain any elements. +func (set *Set) Empty() bool { + return set.tree.Size() == 0 +} + +// Returns number of elements within the set. +func (set *Set) Size() int { + return set.tree.Size() +} + +// Clears all values in the set. +func (set *Set) Clear() { + set.tree.Clear() +} + +// Returns all items in the set. +func (set *Set) Values() []interface{} { + return set.tree.Keys() +} + +func (set *Set) String() string { + str := "TreeSet\n" + items := []string{} + for _, v := range set.tree.Keys() { + items = append(items, fmt.Sprintf("%v", v)) + } + str += strings.Join(items, ", ") + return str +} diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go new file mode 100644 index 0000000..e9c317c --- /dev/null +++ b/sets/treeset/treeset_test.go @@ -0,0 +1,86 @@ +/* +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 treeset + +import ( + "fmt" + "testing" +) + +func TestHashSet(t *testing.T) { + + set := NewWithIntComparator() + + // insertions + 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) + } + + // Asking if a set is superset of nothing, thus it's true + if actualValue := set.Contains(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1, 2, 3); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1, 2, 3, 4); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + // 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) + } + } + + set.Remove() + set.Remove(1) + + if actualValue := set.Contains(1); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + set.Remove(1, 2, 3) + + if actualValue := set.Contains(3); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue := set.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + +}