day25之布隆过滤器的实现和优缺点以及扩展
来源:互联网 发布:软件开发电脑配置 编辑:程序博客网 时间:2024/05/19 08:44
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
代码实现:
//bitMap.hclass BitMap{public: BitMap() {} BitMap(size_t size) { _table.resize((size>>5)+1); } // 1 void Set(int data) { size_t byteNo = data>>5; size_t bitNo = data%32; _table[byteNo] |= (1 << bitNo); } // data所在字节的比特位置0 void ReSet(int data) { size_t byteNo = data>>5; size_t bitNo = data%32; _table[byteNo] &= ~(1<<bitNo); } // 检测是否存在 bool Test(int data) { size_t byteNo = data>>5; size_t bitNo = data%32; if ((1<<bitNo) & _table[byteNo]) return true; return false; }private: std::vector<int> _table;};
//common.h 布隆过滤器用到的散列函数#pragma once#include<string>#include<iostream>using namespace std;size_t GetNextPrim(size_t prev)//prev = 10{ const int _PrimeSize = 28; static const unsigned long _PrimeList [_PrimeSize] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; for (size_t idx = 0; idx < _PrimeSize; ++idx) { if(prev < _PrimeList[idx]) return _PrimeList[idx]; } return -1;}static size_t BKDRHash(const char * str){ unsigned int seed = 131; // 31 131 1313 13131 131313 unsigned int hash = 0; while (*str ) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF);}size_t SDBMHash(const char* str){ register size_t hash = 0; while(size_t ch = (size_t)*str++) { hash = 65599*hash+ch; hash = (size_t)ch+(hash<<6)+ (hash<<16)-hash; } return hash;}size_t RSHash(const char *str){ register size_t hash = 0; size_t magic = 63689; while(size_t ch = (size_t)*str++) { hash = hash * magic +ch; magic *= 378551; } return hash;}size_t APHash(const char* str){ register size_t hash = 0; size_t ch; for (long i = 0; ch = (size_t)*str++; i++) { if (0 == (i&1)) { hash ^= ((hash << 7) ^ (hash >> 3)); } else { hash ^= (~((hash << 11) ^ ch ^ (hash >> 5))); } } return hash;}size_t JSHash(const char* str){ if (!*str) return 0; register size_t hash = 1315423911; while (size_t ch = (size_t)*str++) { hash ^= ((hash << 5) + ch + (hash >> 2)); } return hash;}struct _HashFunc1{ size_t operator()(const string& key) { return BKDRHash(key.c_str()); }};struct _HashFunc2{ size_t operator()(const string& key) { return SDBMHash(key.c_str()); }};struct _HashFunc3{ size_t operator()(const string& key) { return RSHash(key.c_str()); }};struct _HashFunc4{ size_t operator()(const string& key) { return APHash(key.c_str()); }};struct _HashFunc5{ size_t operator()(const string& key) { return JSHash(key.c_str()); }};
#include "bitMap.h"#include "common.h"//哈希函数的用途就是将其他类型的元素转换为整型。template<class K=string, class Hash1 = _HashFunc1, class Hash2 = _HashFunc1,class Hash3 = _HashFunc3, class Hash4 = _HashFunc4, class Hash5 = _HashFunc5 >class BloomFilter{public: BloomFilter(int size = 10) { _capacity = GetNextPrim(size); _bitmap = new BitMap(_capacity); //设置位图大小。 } void Set(const K & key) { _bitmap->Set( Hash1()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 _bitmap->Set( Hash2()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 _bitmap->Set( Hash3()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 _bitmap->Set( Hash4()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 _bitmap->Set( Hash5()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 } //布隆过滤器只要有一个哈希函数计算到不在位图中,这个元素就不在,相反如果计算后都在也有可能不在 bool Find(const K & key) { if ( !_bitmap->Test(Hash1()(key) % _capacity)) { return false; } if ( !_bitmap->Test(Hash2()(key) % _capacity)) { return false; } if ( !_bitmap->Test(Hash3()(key) % _capacity)) { return false; } if ( !_bitmap->Test(Hash4()(key) % _capacity)) { return false; } if ( !_bitmap->Test(Hash5()(key) % _capacity)) { return false; } return true; }private: BitMap *_bitmap; int _capacity; };
布隆过滤器的优点:
布隆过滤器存储空间 插入和查找都是O(1),另外, Hash函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。
缺点:
误算率是其中之一。随着存入的元素数量增加,误算率随之增加
另外,一般情况下不能从布隆过滤器中删除元素
如何扩展BloomFilter使得它支持删除元素的操作?
因为一个布隆过滤器的key对应多个位,冲突的概率比较大,所以不支持删除,因为删除有可能影响到其他元素。如果要对其元素进行删除,就不得不对每一个位进行引用计数。
#include "common.h"//哈希函数的用途就是将其他类型的元素转换为整型。template<class K=string, class Hash1 = _HashFunc1, class Hash2 = _HashFunc1 ,class Hash3 = _HashFunc3, class Hash4 = _HashFunc4, class Hash5 = _HashFunc5 >class BloomFilterCount{public: BloomFilterCount(int size = 10) { _capacity = GetNextPrim(size); _refbm.resize(_capacity); } void Set(const K & key) { size_t hash1=( Hash1()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 size_t hash2=( Hash2()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 size_t hash3=( Hash3()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 size_t hash4=( Hash4()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 size_t hash5=( Hash5()(key) % _capacity ); //可能通过哈希函数计算的整数超过了位图的位数,所以对求模。 _refbm[hash1]++; //对这个位引用计数加加。 _refbm[hash2]++; _refbm[hash3]++; _refbm[hash4]++; _refbm[hash5]++; } void ReSit(const K &key) { size_t hash1=( Hash1()(key) % _capacity ); size_t hash2=( Hash2()(key) % _capacity ); size_t hash3=( Hash3()(key) % _capacity ); size_t hash4=( Hash4()(key) % _capacity ); size_t hash5=( Hash5()(key) % _capacity ); _refbm[hash1]--; //对这个位引用计数减减。 _refbm[hash2]--; _refbm[hash3]--; _refbm[hash4]--; _refbm[hash5]--; } //布隆过滤器只要有一个哈希函数计算到不在位图中,这个元素就不在 bool Find(const K & key) { size_t hash1=( Hash1()(key) % _capacity ); size_t hash2=( Hash2()(key) % _capacity ); size_t hash3=( Hash3()(key) % _capacity ); size_t hash4=( Hash4()(key) % _capacity ); size_t hash5=( Hash5()(key) % _capacity ); if (_refbm[hash1] <= 0) return false; if (_refbm[hash2] <= 0) return false; if (_refbm[hash3] <= 0) return false; if (_refbm[hash4] <= 0) return false; if (_refbm[hash5] <= 0) return false; return true; }//我们都知道,位图非常的节省空间,但由于每一位都要引入一个int,所以空间浪费还是比较严重的, //因此不得不放弃位图了private: vector<size_t> _refbm; size_t _capacity;};
阅读全文
0 0
- day25之布隆过滤器的实现和优缺点以及扩展
- 布隆过滤器的实现及其优缺点
- 简单布隆过滤器实现、布隆过滤器扩展
- 哈希表的扩展-布隆过滤器
- 布隆过滤器的原理、实现和探究
- 布隆过滤器(Bloom Filter)的原理和实现
- 布隆过滤器(Bloom Filter)的原理和实现
- 布隆过滤器(Bloom Filter)的原理和实现
- BS和CS的区别以及优缺点
- OOP以及OOP的基本原则和优缺点
- BS和CS的区别以及优缺点
- protobuf 的优缺点 以及配置和用法
- BS和CS的区别以及优缺点
- BS和CS的区别以及优缺点
- 【数据结构】:哈希的扩展---布隆过滤器
- 【布隆过滤器】实现一个简单的布隆过滤器
- 【布隆过滤器】实现一个简单的布隆过滤器
- 位图和布隆过滤器以及哈希切分
- Linux从入门到无法自拔
- 如何将多sheet Excel 导入到超级表格中
- opengl卡通渲染之逐顶点渲染与逐像素渲染
- 第三届讯飞测试技术嘉年华视频上线
- KMP基本模板理解
- day25之布隆过滤器的实现和优缺点以及扩展
- 浅析Spring事务传播行为和隔离级别
- [C++] 右值引用:移动语义与完美转发
- 探索Tachyon的内存数据存储
- Just a Hook(区间更新)
- 线程安全与不安全
- Scrum认证体系培训和新CSP成长路径所需的SEU
- [RK3288][Android6.0] SoftMAC和FullMAC区别
- LeetCode 77 Combinations (Python详解及实现)