bit数组构建一个非负整数Set集合 [Go]
bit数组构建一个非负整数Set集合
实现了下面这些方法:
func (s *IntSet) Has(x int) bool //不断集合中是否存在元素xfunc (s *IntSet) Add(x int) // 添加元素func (*IntSet) Len() int // return the number of elementsfunc (*IntSet) Remove(x int) // remove x from the setfunc (*IntSet) Clear() // remove all elements from the setfunc (*IntSet) Copy() *IntSet // return a copy of the setfunc (s *IntSet) UnionWith(t *IntSet) // 并集IntersectWith(交集:元素在A集合B集合均出现)DifferenceWith(差集:元素出现在A集合,未出现在B集合)SymmetricDifference(并差集:元素出现在A但没有出现在B,或者出现在B没有出现在A)
intset.go:
package intset
import (
"bytes"
"fmt"
"log"
)
var pc [256]byte
func init() {
for i:= range pc {
pc[i] = pc[i>>1] + byte(i&1)
}
}
type IntSet struct {
words []uint64
}
func (s *IntSet) Has(x int) bool{
word := x / 64
bit := x % 64
return word < len(s.words) && s.words[word]&(1<<bit) != 0
}
func (s *IntSet) Add(x int) {
word, bit := x/64, x%64
for word >= len(s.words) {
s.words = append(s.words, 0)
}
s.words[word] |= 1 << bit
}
// 并集
func (s *IntSet) UnionWith(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] |= tword
} else {
s.words = append(s.words, tword)
}
}
}
// IntersectWith(交集:元素在A集合B集合均出现),
func (s *IntSet) IntersectWith(t *IntSet) {
n1 := len(s.words)
n2 := len(t.words)
minLen := n1
if n2 < n1 {
minLen = n2
}
// 前 minLen 个 word 做按位与
for i := 0; i < minLen; i++ {
s.words[i] &= t.words[i]
}
// s.words 超出的部分清零
for i := minLen; i < n1; i++ {
s.words[i] = 0
}
}
// DifferenceWith(差集:元素出现在A集合,未出现在B集合),
func (s *IntSet) DifferenceWith(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] &^= tword
}
}
}
// SymmetricDifference(并差集:元素出现在A但没有出现在B,或者出现在B没有出现在A)
func (s *IntSet) SymmetricDifference(t *IntSet) {
tCopy := t.Copy()
tCopy.DifferenceWith(s)
s.DifferenceWith(t)
s.UnionWith(tCopy)
}
// PopCount 计算一个64位无符号整数中设置位(值为1的位)的个数
// 参数:
// x - 要计算设置位个数的64位无符号整数
// 返回值:
// int - x中设置位的个数
func PopCount(x uint64) int {
return int(pc[byte(x>>(0*8)) +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))]])
}
// return the number of elements
func (s *IntSet) Len() int {
num := 0
for _, word := range s.words {
if word == 0 {
continue
}
num += PopCount(word)
}
return num
}
// remove x from the set
func (s *IntSet) Remove(x int) {
word, bit := x/64, uint(x%64)
if word > len(s.words) {
log.Printf("集合中不存在该元素:%d\n", x)
}
s.words[word] &^= 1 << bit
}
// remove all elements from the set
func (s *IntSet) Clear() {
s.words = []uint64{}
}
// Copy returns a copy of the set.
func (s *IntSet) Copy() *IntSet {
n := &IntSet{}
n.words = make([]uint64, len(s.words)) // 分配长度
copy(n.words, s.words)
return n
}
//!+string
func (s *IntSet) String() string {
var buf bytes.Buffer
buf.WriteByte('{')
for i, word := range s.words {
if word == 0 {
continue
}
for j:=0; j<64; j++ {
if word & (1 << j) != 0 {
if buf.Len() > 1 {
buf.WriteByte(' ')
}
fmt.Fprintf(&buf, "%d ", 64*i+j)
}
}
}
buf.WriteByte('}')
return buf.String()
}
//!-string
intset_test.go:
package intset
import (
"fmt"
"testing"
)
func TestIntSet(t *testing.T) {
var x, y IntSet
x.Add(1)
x.Add(144)
x.Add(9)
fmt.Println(&x) // "{1 9 144}"
y.Add(9)
y.Add(42)
fmt.Println(y.String()) // "{9 42}"
x.UnionWith(&y)
fmt.Println(x.String()) // "{1 9 42 144}"
fmt.Println(x.Has(9), x.Has(123)) // "true false"
}
var x IntSet
func TestIntSet2(t *testing.T) {
x.Add(1)
x.Add(144)
x.Add(9)
fmt.Println(x.Len())
fmt.Println(x.String())
x.Remove(10)
fmt.Println(x.String())
n := x.Copy()
fmt.Println("x.Copy()", n.String())
fmt.Println("x", x.String())
x.Clear()
fmt.Println("x.Clear()", x.String())
}

浙公网安备 33010602011771号