隨着最後一縷春風拂過,空氣中瀰漫起了夏天的味道,又該滾去學習了。 最近在學習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