Go中Set数据结构的分析与实现
介绍
Set
是值的集合,可以迭代这些值、添加新值、删除值并清除集合、获取集合大小并检查集合是否包含值,集合中的一个值只存储一次,不能重复。
本文代码地址为go-stl
简单实现
这是集合的一个简单实现,还不是并发安全的,为了简单和容易理解而没有引入锁资源。
set.go
package set
type T int
type Set struct {
sets map[T]bool
}
// Add adds a new element to the Set. Returns true if t is not in set.
func (s *Set) Add(t T) bool {
if s.sets == nil {
s.sets = make(map[T]bool)
}
_, ok := s.sets[t]
if !ok {
s.sets[t] = true
}
return !ok
}
// Clear removes all elements from the Set
func (s *Set) Clear() {
s.sets = make(map[T]bool)
}
// Delete removes the Item from the Set and returns true if t is in set
func (s *Set) Delete(t T) bool {
_, ok := s.sets[t]
if ok {
delete(s.sets, t)
}
return ok
}
// Contains returns true if the Set contains the t
func (s *Set) Contains(t T) bool {
_, ok := s.sets[t]
return ok
}
// All returns the all items stored
func (s *Set) All() []T {
var ret []T
for t := range s.sets {
ret = append(ret, t)
}
return ret
}
// Size returns the size of the set
func (s *Set) Size() int {
return len(s.sets)
}
单元测试
这是上面代码的单元测试,它详细解释了如何使用它,以及任何操作的预期结果:
set_test.go
package set
import "testing"
var (
t1 T = 1
t2 T = 2
t3 T = 3
)
func InitSet() *Set {
set := &Set{
}
set.Add(t1)
set.Add(t2)
return set
}
func TestSet_Add(t *testing.T) {
set := InitSet()
ok := set.Add(t1)
if ok {
t.Errorf("There is already %d in set!", t1)
}
ok = set.Add(t3)
if !ok {
t.Errorf("There should be %d in set!", t3)
}
}
func TestSet_Clear(t *testing.T) {
set := InitSet()
set.Clear()
if size := set.Size(); size != 0 {
t.Errorf("wrong count, expected 0 and got %d", size)
}
}
func TestSet_Delete(t *testing