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  }