集合是一种重要的数据结构,集合 Set 不可重复存放数据,会去重,特点就是没有数据会重复。如果两个数据一样,那么只会保存一份数据。集合 Set 可以没有顺序关系,也可以按值排序,算一种特殊的列表。由于字典的键是不重复的,所以只要不考虑字典的值,就可以实现集合,我们来实现存整数的集合 Set
//集合结构体
type Set struct {
m map[int]struct{} //用字典来实现,因为字段不能重复
len int //结合的大小
sync.RWMutex //锁,实现并发安全
}/* 初始化一个集合
新建一个空集合 */
func NewSet(cap int64) *Set {
temp := make(map[int]struct{}, cap)
return &Set{
m: temp,
}
}使用一个容量为 cap 的 map 来实现不可重复集合。map 的值我们不使用,所以值定义为空结构体 struct{},因为空结构体不占用内存空间。如:
package main
import (
"fmt"
"unsafe"
)
func main() {
//为什么使用空结构体
i := struct{}{}
j := struct{}{}
if i == j {
fmt.Printf("输出right:%p
", &i)
}
fmt.Println(unsafe.Sizeof(i))
}
输出right:0x620438
0/* 添加一个元素 */
func (s *Set) Add(item int) {
s.Lock()
defer s.Unlock()
s.m[item] = struct{}{}
s.len = len(s.m)
}首先,加并发锁,实现线程安全,然后往结构体 s *Set 里面的内置 map 添加该元素:item,元素作为字典的键,会自动去重。同时,集合大小重新生成。时间复杂度等于字典设置键值对的复杂度,哈希不冲突的时间复杂度为:O(1),否则为 O(n)。
/* 删除一个元素 */
func (s *Set) Remove(item int) {
s.Lock()
s.Unlock()
//集合没元素直接返回
if s.len == 0 {
return
}
delete(s.m, item) //实际从字典删除这个键
s.len = len(s.m) //重新计算元素数量
}同理,先加并发锁,然后删除 map 里面的键:item。时间复杂度等于字典删除键值对的复杂度,哈希不冲突的时间复杂度为:O(1),否则为 O(n)。
/* 查看是否存在元素 */
func (s *Set) Has(item int) bool {
s.RLock()
defer s.RUnlock()
_, ok := s.m[item]
return ok
}/* 查看集合大小 */
func (s *Set) Len() int {
return s.len
}/* 查看结合是否为空 */
func (s *Set) IsEmpty() bool {
if s.Len() == 0 {
return true
}
return false
}/* 清除所有的集合 */
func (s *Set) Clear() {
s.Lock()
defer s.Unlock()
s.m = map[int]struct{}
s.len = 0
}将原先的 map 释放掉,并且重新赋一个空的 map。时间复杂度:O(1)。
//将集合转化为列表
func (s *Set) List() []int{
s.RLock()
defer s.RUnlock()
list := make([]int,0,s.len)
for item := range s.m{
list = append(list, item)
}
return list
}package main
import (
"fmt"
"sync"
)
//集合结构体
type Set struct {
m map[int]struct{} //用字典来实现,因为字段不能重复
len int //结合的大小
sync.RWMutex //锁,实现并发安全
}
/* 初始化一个集合
新建一个空集合 */
func NewSet(cap int64) *Set {
temp := make(map[int]struct{}, cap)
return &Set{
m: temp,
}
}
/* 添加一个元素 */
func (s *Set) Add(item int) {
s.Lock()
defer s.Unlock()
s.m[item] = struct{}{}
s.len = len(s.m)
}
/* 删除一个元素 */
func (s *Set) Remove(item int) {
s.Lock()
s.Unlock()
//集合没元素直接返回
if s.len == 0 {
return
}
delete(s.m, item) //实际从字典删除这个键
s.len = len(s.m) //重新计算元素数量
}
/* 查看是否存在元素 */
func (s *Set) Has(item int) bool {
s.RLock()
defer s.RUnlock()
_, ok := s.m[item]
return ok
}
/* 查看集合大小 */
func (s *Set) Len() int {
return s.len
}
/* 查看结合是否为空 */
func (s *Set) IsEmpty() bool {
if s.Len() == 0 {
return true
}
return false
}
/* 清除所有的集合 */
func (s *Set) Clear() {
s.Lock()
defer s.Unlock()
s.m = map[int]struct{}{}
s.len = 0
}
//将集合转化为列表
func (s *Set) List() []int {
s.RLock()
defer s.RUnlock()
list := make([]int, 0, s.len)
for item := range s.m {
list = append(list, item)
}
return list
}
func main() {
//初始化一个容量为6的不可重复的集合
s := NewSet(6)
s.Add(2) //添加一个元素2
s.Add(2) //添加一个元素2
s.Add(3) //添加一个元素3
//打印输出
fmt.Println("list of all items", s.List())
//清空集合
s.Clear()
if s.IsEmpty() { //判断集合是否为空
fmt.Println("empty")
}
s.Add(5) //添加一个元素5
s.Add(6) //添加一个元素6
s.Add(7) //添加一个元素7
if s.Has(5) { //判断是否有5这个元素
fmt.Println("5 does exist")
}
s.Remove(5) //移除元素5
s.Remove(6) //移除元素6
fmt.Println("list of all items", s.List())
}
输出:list of all items [2 3]
empty
5 does exist
list of all items [7] | 留言与评论(共有 0 条评论) “” |