github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/sets/treeset/treeset.go (about) 1 // Package treeset implements a tree backed by a red-black tree. 2 // 3 // Structure is not thread safe. 4 // 5 // Reference: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 6 package treeset 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "reflect" 12 "strings" 13 14 "github.com/songzhibin97/go-baseutils/base/bcomparator" 15 "github.com/songzhibin97/go-baseutils/structure/sets" 16 "github.com/songzhibin97/go-baseutils/structure/trees/redblacktree" 17 ) 18 19 var _ sets.Set[any] = (*Set[any])(nil) 20 21 // Set holds elements in a red-black tree 22 type Set[E any] struct { 23 tree *redblacktree.Tree[E, struct{}] 24 zero E 25 } 26 27 var itemExists = struct{}{} 28 29 // NewWith instantiates a new empty set with the custom comparator. 30 func NewWith[E any](comparator bcomparator.Comparator[E], values ...E) *Set[E] { 31 set := &Set[E]{tree: redblacktree.NewWith[E, struct{}](comparator)} 32 if len(values) > 0 { 33 set.Add(values...) 34 } 35 return set 36 } 37 38 // NewWithIntComparator instantiates a new empty set with the IntComparator, i.e. keys are of type int. 39 func NewWithIntComparator(values ...int) *Set[int] { 40 set := &Set[int]{tree: redblacktree.NewWithIntComparator[struct{}]()} 41 if len(values) > 0 { 42 set.Add(values...) 43 } 44 return set 45 } 46 47 // NewWithStringComparator instantiates a new empty set with the StringComparator, i.e. keys are of type string. 48 func NewWithStringComparator(values ...string) *Set[string] { 49 set := &Set[string]{tree: redblacktree.NewWithStringComparator[struct{}]()} 50 if len(values) > 0 { 51 set.Add(values...) 52 } 53 return set 54 } 55 56 // Add adds the items (one or more) to the set. 57 func (set *Set[E]) Add(items ...E) { 58 for _, item := range items { 59 set.tree.Put(item, itemExists) 60 } 61 } 62 63 // Remove removes the items (one or more) from the set. 64 func (set *Set[E]) Remove(items ...E) { 65 for _, item := range items { 66 set.tree.Remove(item) 67 } 68 } 69 70 // Contains checks weather items (one or more) are present in the set. 71 // All items have to be present in the set for the method to return true. 72 // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. 73 func (set *Set[E]) Contains(items ...E) bool { 74 for _, item := range items { 75 if _, contains := set.tree.Get(item); !contains { 76 return false 77 } 78 } 79 return true 80 } 81 82 // Empty returns true if set does not contain any elements. 83 func (set *Set[E]) Empty() bool { 84 return set.tree.Size() == 0 85 } 86 87 // Size returns number of elements within the set. 88 func (set *Set[E]) Size() int { 89 return set.tree.Size() 90 } 91 92 // Clear clears all values in the set. 93 func (set *Set[E]) Clear() { 94 set.tree.Clear() 95 } 96 97 // Values returns all items in the set. 98 func (set *Set[E]) Values() []E { 99 return set.tree.Keys() 100 } 101 102 // String returns a string representation of container 103 func (set *Set[E]) String() string { 104 b := strings.Builder{} 105 b.WriteString("TreeSet\n") 106 for _, v := range set.tree.Keys() { 107 b.WriteString(fmt.Sprintf("(key:%v) ", v)) 108 } 109 return b.String() 110 } 111 112 // Intersection returns the intersection between two sets. 113 // The new set consists of all elements that are both in "set" and "another". 114 // The two sets should have the same comparators, otherwise the result is empty set. 115 // Ref: https://en.wikipedia.org/wiki/Intersection_(set_theory) 116 func (set *Set[E]) Intersection(another *Set[E]) *Set[E] { 117 result := NewWith(set.tree.Comparator) 118 119 setComparator := reflect.ValueOf(set.tree.Comparator) 120 anotherComparator := reflect.ValueOf(another.tree.Comparator) 121 if setComparator.Pointer() != anotherComparator.Pointer() { 122 return result 123 } 124 125 // Iterate over smaller set (optimization) 126 if set.Size() <= another.Size() { 127 for it := set.Iterator(); it.Next(); { 128 if another.Contains(it.Value()) { 129 result.Add(it.Value()) 130 } 131 } 132 } else { 133 for it := another.Iterator(); it.Next(); { 134 if set.Contains(it.Value()) { 135 result.Add(it.Value()) 136 } 137 } 138 } 139 140 return result 141 } 142 143 // Union returns the union of two sets. 144 // The new set consists of all elements that are in "set" or "another" (possibly both). 145 // The two sets should have the same comparators, otherwise the result is empty set. 146 // Ref: https://en.wikipedia.org/wiki/Union_(set_theory) 147 func (set *Set[E]) Union(another *Set[E]) *Set[E] { 148 result := NewWith(set.tree.Comparator) 149 150 setComparator := reflect.ValueOf(set.tree.Comparator) 151 anotherComparator := reflect.ValueOf(another.tree.Comparator) 152 if setComparator.Pointer() != anotherComparator.Pointer() { 153 return result 154 } 155 156 for it := set.Iterator(); it.Next(); { 157 result.Add(it.Value()) 158 } 159 for it := another.Iterator(); it.Next(); { 160 result.Add(it.Value()) 161 } 162 163 return result 164 } 165 166 // Difference returns the difference between two sets. 167 // The two sets should have the same comparators, otherwise the result is empty set. 168 // The new set consists of all elements that are in "set" but not in "another". 169 // Ref: https://proofwiki.org/wiki/Definition:Set_Difference 170 func (set *Set[E]) Difference(another *Set[E]) *Set[E] { 171 result := NewWith(set.tree.Comparator) 172 173 for it := set.Iterator(); it.Next(); { 174 if !another.Contains(it.Value()) { 175 result.Add(it.Value()) 176 } 177 } 178 179 return result 180 } 181 182 // UnmarshalJSON @implements json.Unmarshaler 183 func (set *Set[E]) UnmarshalJSON(bytes []byte) error { 184 elements := []E{} 185 err := json.Unmarshal(bytes, &elements) 186 if err == nil { 187 set.Clear() 188 set.Add(elements...) 189 } 190 return err 191 } 192 193 // MarshalJSON @implements json.Marshaler 194 func (set *Set[E]) MarshalJSON() ([]byte, error) { 195 return json.Marshal(set.Values()) 196 }