package ds // ds-set.go // 泛型集合,基于 map[T]struct{}。T 约束为 comparable。 // Add/Remove/Contains 均 O(1) 均摊。支持并集/交集/差集。 // 比 map[T]bool 更省内存(空结构体不占空间),语义也更清晰。 // Set 泛型集合,零值不可直接用(map 零值不能写),必须用 NewSet。 type Set[T comparable] struct { m map[T]struct{} } // NewSet 创建空集合。 func NewSet[T comparable]() *Set[T] { return &Set[T]{m: make(map[T]struct{})} } // NewSetFrom 从切片创建集合,自动去重。 func NewSetFrom[T comparable](vals []T) *Set[T] { s := NewSet[T]() for _, v := range vals { s.m[v] = struct{}{} } return s } // Add 添加元素,已存在则无操作。 func (s *Set[T]) Add(v T) { s.m[v] = struct{}{} } // Remove 删除元素,不存在则无操作。 func (s *Set[T]) Remove(v T) { delete(s.m, v) } // Contains 是否包含元素。 func (s *Set[T]) Contains(v T) bool { _, ok := s.m[v] return ok } // Len 元素个数。 func (s *Set[T]) Len() int { return len(s.m) } // Empty 是否为空。 func (s *Set[T]) Empty() bool { return len(s.m) == 0 } // ToSlice 转为切片。map 遍历顺序无序,如需稳定顺序需自行排序。 func (s *Set[T]) ToSlice() []T { out := make([]T, 0, len(s.m)) for v := range s.m { out = append(out, v) } return out } // Union 并集:返回新集合,包含 s 和 other 的所有元素。 func (s *Set[T]) Union(other *Set[T]) *Set[T] { r := NewSet[T]() for v := range s.m { r.m[v] = struct{}{} } for v := range other.m { r.m[v] = struct{}{} } return r } // Intersect 交集:返回新集合,仅包含 s 和 other 都有的元素。 func (s *Set[T]) Intersect(other *Set[T]) *Set[T] { r := NewSet[T]() // 遍历较小集合,降低常数 small, big := s, other if small.Len() > big.Len() { small, big = big, small } for v := range small.m { if _, ok := big.m[v]; ok { r.m[v] = struct{}{} } } return r } // Difference 差集:返回新集合,包含在 s 中但不在 other 中的元素。 func (s *Set[T]) Difference(other *Set[T]) *Set[T] { r := NewSet[T]() for v := range s.m { if _, ok := other.m[v]; !ok { r.m[v] = struct{}{} } } return r }