golang实现位图(BitSet)
一, 概念
Bitmap (位图)是一个十分有用的数据结构。所谓的 Bit-map 就是用一个 bit 位来标记某个元素对应的 Value,而 Key 即是该元素。由于采用了 Bit 为单位来存储数据,因此在内存占用方面,可以大大节省。(《编程珠玑》第一章引入的问题,提到了 Bitmap)
二, 实现基本原理
类似于java的BitSet, 是位操作的对象,值只有0或1,内部维护了一个long数组,初始只有一个long,所以BitSet最小的size是64,当随着存储的元素越来越多,BitSet内部会动态扩充,最终内部是由N个long来存储,这些针对操作都是透明的。 用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。使用用的时候既可根据某一个是否为0表示,此数是否出现过。 一个1G的空间,有 8*1024*1024*1024=8.58*10^9bit,也就是可以表示85亿个不同的数
三, 代码实现 1. 实现操作set: 将指定位置置为1. 2. 实现操作clear: 将指定位置置为0. 3. 实现操作get: 查找指定位置的值. 4. 容量自动扩展.
二, 实现基本原理
类似于java的BitSet, 是位操作的对象,值只有0或1,内部维护了一个long数组,初始只有一个long,所以BitSet最小的size是64,当随着存储的元素越来越多,BitSet内部会动态扩充,最终内部是由N个long来存储,这些针对操作都是透明的。 用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。使用用的时候既可根据某一个是否为0表示,此数是否出现过。 一个1G的空间,有 8*1024*1024*1024=8.58*10^9bit,也就是可以表示85亿个不同的数
三, 代码实现 1. 实现操作set: 将指定位置置为1. 2. 实现操作clear: 将指定位置置为0. 3. 实现操作get: 查找指定位置的值. 4. 容量自动扩展.
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 } }5. 使用举例: 查找指定数字, 在数列中是否出现. (由于位图很节省空间, 所以比较适合单击大数据的查找)
func start_bitMap() { bMap := NewBitMap(64) for i := 100; i < 1000; i++ { bMap.set(uint64(i)) } fmt.Printf("bmap第133个位置:%v ", bMap.get(133)) fmt.Printf("bmap2string:%s ", bMap.toString()) fmt.Printf("end:cap=%d,len=%d ", cap(*bMap), len(*bMap)) }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。