算法学习 - Bloom Filter(布隆过滤器)学习实现(C++实现)
2015-03-25 02:07
585 查看
Bloom filter简介
Bloom Filter计算方法
Bloom Filter优点缺点
优点
缺点
图示说明
非常感谢评论里指出了我代码里的小问题。以下代码修改了一下,主要是在第二次 HasH 的时候有小问题。
以上文字来源百度百科
保存的不是数据本身,安全性好。
不能删除元素。
第一次插入
第二次插入
这样就存放了
但是假如我们查找的
下面写下我用C++写的代码实现,比较简单的实现了下,具体的Hash算法我都简略的写了。
首先是头文件
头文件保存好,放到工程路径下。
下面是
这就是我的代码了。
Bloom Filter计算方法
Bloom Filter优点缺点
优点
缺点
图示说明
非常感谢评论里指出了我代码里的小问题。以下代码修改了一下,主要是在第二次 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 ]
第一次插入
a用两个哈希函数,映射到
1 4位置上,变为1.
[ 1 0 0 1 0 0 0 0 0 0 ]
第二次插入
b同样的hash函数,映射到
1 8位置上, 变为1.
[ 1 0 0 1 0 0 0 1 0 0 ]
这样就存放了
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
头文件保存好,放到工程路径下。
下面是
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; }
这就是我的代码了。
相关文章推荐
- 算法学习-桶排序(Bucket Sort) C++实现
- 算法学习 - 堆排序 ( HeapSort ) C++实现
- 【学习】关于电梯算法的C++实现
- 学习算法 - 表指针实现~ C++
- 机器学习决策树学习算法(C++实现)
- 算法学习 - 括号匹配(栈实现)C++
- 算法学习 - 选择排序的稳定性讨论(C++实现)
- 算法学习 - Gray Code(格雷码)的解释和c++实现
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 习题2.8 随机数组的三种生成算法(补) 将bash的实现翻译成比较纯正的bash风格
- 算法学习 - 后缀表达式 (C++ 栈实现)
- 算法学习 - Bellman-Ford(贝尔曼福特)算法(C++实现)
- 算法学习 - 欧几里得算法(辗转相除法)(c++实现)
- 经典算法学习————快速排序算法的c++实现
- 算法学习记录五(C++)--->两个栈实现队列
- 算法学习 - 快速幂和矩阵快速幂(复杂度Olog(n))C++实现
- 算法学习-哈夫曼编码(c++实现)
- 算法学习 - 链表的游标实现~ C++
- 【算法学习】B-Tree编程实现(C++模板类封装)
- 算法学习——搜索和C++ STL 实现全排列和去重全排列
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(7)习题2.8 随机数组的三种生成算法