1.BitSet是什么
BitSet是借鉴位图(BitMap)概念创造的一个数据结构。所谓的BitMap 就是用一个 bit 位来标记某个元素对应的 Value,而 Key 即是该元素。由于采用了 Bit 为单位来存储数据,因此在内存占用方面,可以大大节省。(《编程珠玑》第一章引入的问题,提到了 Bitmap)
BitSet的好处是用很小的空间标记已存的数据(每一bit对应)。
在查找中,我们可以通过map、hash等结构进行查找;但如果存在大量数据,map和hash将会大量占用内存,会导致一系列问题。
2.BitSet的C++用法
在C++中,BitSet是STL之一,具体用法如下:
1)构造函数:
std::bitset<16> foo;
std::bitset<4> foo (std::string("1001"));
2)访问函数
operator[] :Access bit (public member function )
count: Count bits set (public member function )
size: Return size (public member function )
test: Return bit value (public member function )
any: Test if any bit is set (public member function )
none: Test if no bit is set (public member function )
all: Test if all bits are set (public member function )
3)Bit操作函数
set: Set bits (public member function )
reset: Reset bits (public member function )
flip: Flip bits (public member function )
4)转换函数:
to_string: Convert to string (public member function )
to_ulong: Convert to unsigned long integer (public member function )
to_ullong: Convert to unsigned long long (public member function )
3.golang中的BitSet
golang中没有现成的BitSet库,但多个人提供了写法。
1)可参考github.com/willf/bitset,该库提供了完整的BitSet用法,其中添加元素用Set,判断元素是否存在用Test。同时,该方法的实现仅提供了
2)另一个实现的比较简单,原代码链接为https://blog.csdn.net/kdpujie/article/details/56488546:
import (
"bytes"
)
//bitSet实现
type BitSet []uint64
const (
Address_Bits_Per_Word uint8 = 6
Words_Per_Size uint64 = 64 //单字64位
)
//创建指定初始化大小的bitSet
func NewBitMap(nbits int) *BitSet {
wordsLen := (nbits - 1) >> Address_Bits_Per_Word
temp := BitSet(make([]uint64, wordsLen+1, wordsLen+1))
return &temp
}
//把指定位置设为ture
func (this *BitSet) Set(bitIndex uint64) {
wIndex := this.wordIndex(bitIndex)
this.expandTo(wIndex)
(*this)[wIndex] |= uint64(0x01) << (bitIndex % Words_Per_Size)
}
//设置指定位置为false
func (this *BitSet) Clear(bitIndex uint64) {
wIndex := this.wordIndex(bitIndex)
if wIndex < len(*this) {
(*this)[wIndex] &^= uint64(0x01) << (bitIndex % Words_Per_Size)
}
}
//获取指定位置的值
func (this *BitSet) Get(bitIndex uint64) bool {
wIndex := this.wordIndex(bitIndex)
return (wIndex < len(*this)) && ((*this)[wIndex]&(uint64(0x01)<<(bitIndex%Words_Per_Size)) != 0)
}
//以二进制串的格式打印bitMap内容
func (this *BitSet) ToString() string {
var temp uint64
strAppend := &bytes.Buffer{}
for i := 0; i < len(*this); i++ {
temp = (*this)[i]
for j := 0; j < 64; j++ {
if temp&(uint64(0x01)<<uint64(j)) != 0 {
strAppend.WriteString("1")
} else {
strAppend.WriteString("0")
}
}
}
return strAppend.String()
}
//定位位置
func (this BitSet) wordIndex(bitIndex uint64) int {
return int(bitIndex >> Address_Bits_Per_Word)
}
//扩容:每次扩容两倍
func (this *BitSet) expandTo(wordIndex int) {
wordsRequired := wordIndex + 1
if len(*this) < wordsRequired {
if wordsRequired < 2*len(*this) {
wordsRequired = 2 * len(*this)
}
newCap := make([]uint64, wordsRequired, wordsRequired)
copy(newCap, *this)
(*this) = newCap
}
}
这个实现为uint64位。
大家可以根据实际采用BitSet,并可自己根据原理来实现。