packagebitmapimport("bytes""fmt")// 参考go语言圣经6.5章节
// UINTSIZE 判断当前机器是32位还是64位
// 64位机器^uint(0) = 64位全1,>> 63之后变成只有第一位为1,32 << 1 = 64
// 32位机器>> 63之后全部位变为0,32 << 0 = 32
constUINTSIZE=32<<(^uint(0)>>63)// An IntSet is a set of small non-negative integers.
// Its zero value represents the empty set.
typeIntSetstruct{words[]uint}// Has reports whether the set contains the non-negative value x.
func(s*IntSet)Has(xint)bool{word,bit:=x/UINTSIZE,uint(x%UINTSIZE)// words长度大于数据所在元素下标,且所在bit位不为0
returnword<len(s.words)&&s.words[word]&(1<<bit)!=0}// Add adds the non-negative value x to the set.
func(s*IntSet)Add(xint){// 对要存储的数取商和模
word,bit:=x/UINTSIZE,uint(x%UINTSIZE)// 如果words数组长度小于商,则扩容至能存下为止
forword>=len(s.words){s.words=append(s.words,0)}// 将数存储到指定bit位
s.words[word]|=1<<bit}// UnionWith sets s to the union of s and t.
// 设置s为s和t的并集
func(s*IntSet)UnionWith(t*IntSet){fori,tword:=ranget.words{ifi<len(s.words){// 取并集
// 101 | 010 = 111
s.words[i]|=tword}else{s.words=append(s.words,tword)}}}// IntersectWith sets s to the intersect of s and t
// 设置s为s和t的交集
// 元素在s集合t集合均出现
func(s*IntSet)IntersectWith(t*IntSet){// 如果s比t长,把s截取到t的长度
iflen(s.words)>len(t.words){s.words=s.words[:len(t.words)]}// 如果t比s长,也只会比较s中有的部分
fori,tword:=ranget.words{ifi<len(s.words){s.words[i]&=tword}}}// DifferenceWith sets s to the difference of s and t
// 设置s为s和t的差集
// 元素出现在s集合,未出现在t集合
func(s*IntSet)DifferenceWith(t*IntSet){fori,tword:=ranget.words{ifi<len(s.words){// ^: 异或运算,值不同则为1,相同为0
// B A
// 100011010 ^ 110101001 = 010110011
// 010110011 & 110101001 = 010100001
// 正好是A中有而B中没有的
s.words[i]&=s.words[i]^tword}}}// SymmetricDifference sets s to the symmetric difference of s and t
// 设置s为s和t的并查集
// 元素出现在s但没有出现在t,或者出现在t没有出现在s
func(s*IntSet)SymmetricDifference(t*IntSet){fori,tword:=ranget.words{ifi<len(s.words){s.words[i]^=tword}else{// 如果s元素个数小于t,则s要把t中多的部分补上
s.words=append(s.words,tword)}}}// String returns the set as a string of the form "{1 2 3}".
// String方法,fmt.Printf()函数对实现了String方法的类型会直接调用其String()方法进行输出
func(s*IntSet)String()string{varbufbytes.Bufferbuf.WriteByte('{')fori,word:=ranges.words{ifword==0{continue}// 逐位遍历,如果为1,则将其写入缓冲区
forj:=0;j<UINTSIZE;j++{ifword&(1<<uint(j))!=0{ifbuf.Len()>len("{"){buf.WriteByte(' ')}// UINTSIZE*i+j还原数实际大小
// 比如2存储在[0]的第2个比特位
// UINTSIZE*0+2=2
fmt.Fprintf(&buf,"%d",UINTSIZE*i+j)}}}buf.WriteByte('}')returnbuf.String()}// Len return the number of elements
// 返回当前存储了多少个数
func(s*IntSet)Len()int{l:=0for_,word:=ranges.words{ifword==0{continue}forj:=0;j<UINTSIZE;j++{ifword&(1<<uint(j))!=0{l++}}}returnl}// Elems returns a slice containing the elements of the set
func(s*IntSet)Elems()[]int{res:=make([]int,s.Len())k:=0fori,word:=ranges.words{ifword==0{continue}forj:=0;j<UINTSIZE;j++{ifword&(1<<j)!=0{res[k]=UINTSIZE*i+jk++}}}returnres}// Remove remove x from the set
// 删除指定数
func(s*IntSet)Remove(xint){word,bit:=x/UINTSIZE,uint(x%UINTSIZE)// 如果要删除的数超出长度或words为空
ifword>len(s.words)||len(s.words)==0{return}// 将指定bit位置0,^为取反符号
// ^(1<<2)
// = ^(001 << 2)
// = ^100
// = 011
s.words[word]&=^(1<<bit)}// Clear remove all elements from the set
func(s*IntSet)Clear(){fori:=ranges.words{s.words[i]=0}}// Copy return a copy of the set
func(s*IntSet)Copy()*IntSet{c:=new(IntSet)c.words=make([]uint,len(s.words))copy(c.words,s.words)returnc}// AddAll adds all the non-negative value num from nums to the set.
func(s*IntSet)AddAll(nums...int){for_,num:=rangenums{s.Add(num)}}