Goに慣れるためとアルゴリズムの復習の為に週1ぐらいで更新していきます。アルゴリズムクイックリファレンス 第2版を読んで各種アルゴリズムをGoで実装して行きます。
前回: Goでのアルゴリズムクイックリファレンス第2版(ハッシュに基づいた探索)
今回はブルームフィルタ
ブルームフィルタ(Bloom Filter)は、1970年に Burton H. Bloom が考案した空間効率の良い確率的データ構造であり、要素が集合のメンバーであるかどうかのテストに使われる。偽陽性(False Positive)による誤検出の可能性があるが、偽陰性(False Negative)はない。要素を集合に追加することができるが、削除することはできない(Counting filter を使えば削除できる)。集合に要素が追加されればされるほど、偽陽性の可能性が高くなる。
- アルゴリズム
- 全て 0 に設定された m ビットのビット配列
- k 個のハッシュ関数が定義されており、それぞれがキー値を m 個の配列位置のいずれかにマッピング
package main
import "fmt"
const SIZE = 1999
func hashes(a *[]int) []int {
xs := []int{0, 0, 0}
for _, v := range *a {
xs[0] = xs[0]*137 + v
xs[1] = xs[1]*69 + v
xs[2] = xs[2]*545 + v
}
hashes := make([]int, 3)
for i, _ := range xs {
hashes[i] = xs[i] % SIZE
}
return hashes
}
type BloomFilter struct {
BitArray *[]int
}
func (bf *BloomFilter) add(a *[]int) {
for _, v := range hashes(a) {
(*bf.BitArray)[v] = 1
}
}
func (bf *BloomFilter) query(a *[]int) bool {
for _, v := range hashes(a) {
if (*bf.BitArray)[v] == 0 {
return false
}
}
return true
}
func main() {
ba := make([]int, 0)
for i := 0; i < SIZE; i++ {
ba = append(ba, 0)
}
bf := &BloomFilter{&ba}
ary := []int{1, 2, 3}
bf.add(&ary)
if bf.query(&ary) {
fmt.Println("ok")
}
ary2 := []int{1, 2, 3, 4}
if !bf.query(&ary2) {
fmt.Println("ng")
}
}
西尾さんのblogにあった実装を参考にさせていただきました。
次回は二分探索木です。