golang的BitSet

18 篇文章 0 订阅

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,并可自己根据原理来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值