当前位置:   article > 正文

算法学习 - Bloom Filter(布隆过滤器)学习实现(C++实现)_实例学习bloom filter c++

实例学习bloom filter c++

非常感谢评论里指出了我代码里的小问题。以下代码修改了一下,主要是在第二次 HasH 的时候有小问题。

Bloom filter简介

Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员。如果检测结果为是,该元素不一定在集合中;但如果检测结果为否,该元素一定不在集合中。因此Bloom filter具有100%的召回率。这样每个检测请求返回有“在集合内(可能错误)”和“不在集合内(绝对不在集合内)”两种情况,可见 Bloom filter 是牺牲了正确率和时间以节省空间。

以上文字来源百度百科

Bloom Filter计算方法

如需要判断一个元素是不是在一个集合中,我们通常做法是把所有元素保存下来,然后通过比较知道它是不是在集合内,链表、树都是基于这种思路,当集合内元素个数的变大,我们需要的空间和时间都线性变大,检索速度也越来越慢。 Bloom filter 采用的是哈希函数的方法,将一个元素映射到一个 m 长度的阵列上的一个点,当这个点是 1 时,那么这个元素在集合内,反之则不在集合内。这个方法的缺点就是当检测的元素很多的时候可能有冲突,解决方法就是使用 k 个哈希 函数对应 k 个点,如果所有点都是 1 的话,那么元素在集合内,如果有 0 的话,元素则不在集合内。

Bloom Filter优点缺点

优点

  • 插入时间和查询时间都是常数。
  • 保存的不是数据本身,安全性好。

缺点

  • 插入的元素越多,错判性越大。
  • 不能删除元素。

图示说明

例如我们有一个简单的Bloom Filter结构如下:(所有位都是0)

      [ 0 0 0 0 0 0 0 0 0 0 ]
  • 1

第一次插入a用两个哈希函数,映射到1 4位置上,变为1.

      [ 1 0 0 1 0 0 0 0 0 0 ]
  • 1

第二次插入b同样的hash函数,映射到1 8位置上, 变为1.

      [ 1 0 0 1 0 0 0 1 0 0 ]
  • 1

这样就存放了a b两个元素,当我们查找a是否在的时候,两次hash找到1 4位置,发现同时为 1。则表明a存在。

但是假如我们查找的d哈希后映射到4 8位置,发现也同时为 1. 认为存在,这就出错了,因为现在里面只存放了a b没有d

下面写下我用C++写的代码实现,比较简单的实现了下,具体的Hash算法我都简略的写了。

首先是头文件Header.h

//
//  Header.h
//  BloomFilter
//
//  Created by Alps on 15/3/19.
//  Copyright (c) 2015年 chen. All rights reserved.
//

#ifndef BloomFilter_Header_h
#define BloomFilter_Header_h

class BitMap{
public:
    BitMap(){
        bitmap = NULL;
        size = 0;
    }
    BitMap(int size){
        bitmap = NULL;
        bitmap = new char[size];
        if (bitmap == NULL) {
            printf("ErroR In BitMap Constractor!\n");
        }else{
            memset(bitmap, 0x0, size * sizeof(char));
            this->size = size;
        }
    }

    int initBitMap(int size){
        bitmap = NULL;
        bitmap = new char[size];
        if (bitmap == NULL) {
            printf("ErroR In BitMap Constractor!\n");
            return 0;
        }else{
            memset(bitmap, 0x0, size * sizeof(char));
            this->size = size;
            return this->size;
        }
    }


    /*
     * set the index bit to 1;
     */
    int bitmapSet(int index){
        int addr = index/8;
        int addroffset = index%8;
        unsigned char temp = 0x1 << addroffset;
        if (addr > (size+1)) {
            return 0;
        }else{
            bitmap[addr] |= temp;
            return 1;
        }
    }

    /*
     * return if the index in bitmap is 1;
     */
    int bitmapGet(int index){
        int addr = index/8;
        int addroffset = index%8;
        unsigned char temp = 0x1 << addroffset;
        if (addr > (size + 1)) {
            return 0;
        }else{
            return (bitmap[addr] & temp) > 0 ? 1 : 0;
        }
    }

    /*
     * del the index from 1 to 0
     */
    int bitmapDel(int index){
        if (bitmapGet(index) == 0) {
            return 0;
        }
        int addr = index/8;
        int addroffset = index%8;
        unsigned char temp = 0x1 << addroffset;
        if (addr > (size + 1)) {
            return 0;
        }else{
            bitmap[addr] ^= temp;
            return 1;
        }
    }

private:
    char *bitmap;
    int size;
};

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

头文件保存好,放到工程路径下。
下面是BloomFilter.cpp文件了。

//
//  main.cpp
//  BloomFilter
//
//  Created by Alps on 15/3/18.
//  Copyright (c) 2015年 chen. All rights reserved.
//

#include <iostream>
#include "Header.h"
using namespace std;


template <class Type> class BloomFilter{
public:
    BloomFilter();
    BloomFilter(int length){
        bitmap.initBitMap(length);
        this->length = length;
    }
    bool Add(const Type &T);
    bool Contains(const Type &T);
    int HasH(const Type &T);
    int SecondHasH(const Type &T);
private:
    BitMap bitmap;
    int length;
};
template <class Type> int BloomFilter<Type>::HasH(const Type &T){
    int temp = (int) T;
    return temp%length;
}

template <class Type> int BloomFilter<Type>::SecondHasH(const Type &T){
    int temp = (int) T;
    return temp%9973;
    //这里直接选了一个大素数 请各位自己优化自己的 HasH函数
    //不然会出现频繁的哈希冲突,并且把布隆过滤器的大小尽量放大一点几百万都可以
}

template <class Type> bool BloomFilter<Type>::Add(const Type &T){
    int first = HasH(T);
    int second = SecondHasH(first);
    if (bitmap.bitmapSet(first) && bitmap.bitmapSet(second)) {
        return true;
    }else{
        return false;
    }

}

template <class Type> bool BloomFilter<Type>::Contains(const Type &T){
    int first = HasH(T);
    int second =  SecondHasH(T);
    if (bitmap.bitmapGet(first) && bitmap.bitmapGet(second)) {
        return true;
    }else{
        return false;
    }
}




int main(int argc, const char * argv[]) {

    BloomFilter<int> bloom(10);

    bloom.Add(3);
    if (bloom.Contains(3)) {
        printf("true\n");
    }else{
        printf("false\n");
    }

    if (bloom.Contains(2)) {
        printf("true\n");
    }else{
        printf("false\n");
    }

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

这就是我的代码了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/763072
推荐阅读
相关标签
  

闽ICP备14008679号