随着最后一缕春风拂过,空气中弥漫起了夏天的味道,又该滚去学习了。 最近在学习Redis,发现了一个好玩的东西叫布隆过滤器。但是个人水平又不足以研究源码,那我就本身写一个简单的玩玩。程序员
请原谅个人班门弄斧。我认为布隆过滤器就是用来判断key是否存在的,基于位图。有一个特色是,若是我说key不存在,那么您能够彻底信任我,若是我说key存在,您可能就要掂量一下啦。恩恩,具体说来就是来了一个key,咱们对其进行n次不一样的hash,生成n个bit的索引,在位图里将这几个bit置成1,再来了另外一个key,对其进行相同的hash,看看生成的索引对应的bit是否都为1,都为1即为(可能)存在,反之(必定)不存在。至于为何会出现这种不许确的状况,能够去google一下,比我讲得清楚多了。算法
首先,咱们须要一个位图,既然决定纯手写,那就从0开始DIY了。 老爷请上码:学习
type BM int64
//用切片来充当位图,切片的每一个位与二级制位方向正好相反
type BitMap struct {
BitSlice []BM
BitNum uint
}
//求一个BM的bit数,确定有更好的计算方法
var bmBitNum = uint(unsafe.Sizeof(BM(1)) * 8)
//n为须要的bit数
func NewBitMap(n int) *BitMap {
//计算须要几个元素bit才可以
bitNum := uint(n) / bmBitNum + 1
return &BitMap {
BitSlice : make([]BM,bitNum,bitNum),
BitNum : uint(n),
}
}
//n为位图的索引
func (bm *BitMap) Set (n uint) {
if n > bm.BitNum {
return
}
//求出应该是切片的第几个元素
byteIndex := n / bmBitNum
//求出是此元素的第几个bit
bitIndex := n % bmBitNum
//经过位运算将该bit置成1
bm.BitSlice[byteIndex] |= BM(uint(1) << bitIndex)
}
//一样的思路去找所在bit是否已经被置成1
func (bm *BitMap) Get (n uint) bool{
if n > bm.BitNum {
return false
}
byteIndex := n / bmBitNum
bitIndex := n % bmBitNum
return (bm.BitSlice[byteIndex] & BM(uint(1) << bitIndex)) != 0
}
复制代码
OK,就这样咱们完成了一个简单的位图。至于之后的各类优化只能等我水平高一些来再续前缘了。 有了位图就能够搞布隆过滤器了。 老弟来了:优化
//这里的两个切片是用来hash的,mod里最大的质数为101,我准备用3个hash生成3个bit,hash事后生成的最大的bit为101。
var cap = []uint{7, 11, 13}
var mod = []uint{31, 37, 101}
//刚刚手写的位图派上用场了
type BloomFilter struct {
BitMap *bitMap.BitMap
}
//n依旧为须要的位数
func NewBloomFilter(n int) *BloomFilter {
return &BloomFilter {
BitMap:bitMap.NewBitMap(n),
}
}
//通过3次hash
func (bf BloomFilter) Set(value string) {
for i := 0; i < len(cap); i++ {
bf.BitMap.Set(hash(value,i))
}
}
//一样规则的三次hash判是否存在
func (bf BloomFilter) Exist(value string) bool {
for i := 0; i < len(cap); i++ {
if !bf.BitMap.Get(hash(value,i)) {
return false
}
}
return true
}
//我本身写的hash算法,浓浓的乡土气息。等我再学习一段时间确定能搞一个更好的!
func hash(s string,index int) uint {
bit := uint(1)
for i := 0; i < len(s); i++ {
bit = (bit * cap[index] + (uint(s[i] - 'a') + uint(1))) % mod[index]
}
return bit
}
复制代码
好了,就是这样。其实我只是想说,学习任何东西,要从原理抓起,要疯狂地实践。不要拿半路转行的码农不当程序员哦。ui
最后,分享一个公众号吧,叫作算法梦想家,来跟我一块儿玩算法,玩音乐,聊聊文学创做,我们一块儿天马行空!google