议题:布隆过滤器(Bloom Filter)

分析:

  • BF由一个很长的二进制向量和一系列随机映射的函数组成,通过多个Hash函数将一个元素映射到一个Bit Array中的多个点,查询的时候仅当所有的映射点都为1才能判断元素存在于集合内;BF用于检索一个元素是否在一个集合中,记忆集合求交集;优点是空间 和时间效率都超过一般查询算法,缺点是有一定的误判概率和删除困难;

  • 如下图,使用三个哈希函数对每个元素进行映射,这样每个元素对应HashTable中的三个位置,如果查找w是否在HashTable中则仍旧利用三个哈 希函数对其进行映射,当且仅当三个哈希函数映射的位置的标记都为1的时候,才表明w存在于集合中;但是由于HashTable中的每一个位由所有映射元素 共享,w的三个映射位置可能分别被其他元素标记,所以此方法存在一定误判的概率;

  • 位数组表示所有单元数据是否存在,K个独立Hash函数用于判断某个元素是否已经存在。存入一个数据时将K个独立Hash函数映射的位都置位1,检测新数 据是否存在位数组中时再次计算K个独立Hash函数,如果所有的映射位都为1,则说明数据重复;只要有一个独立Hash函数的映射结果不为1说明数据没有 重复;

  • 由于位数组中每一个位可能同时对应多个数据的映射,所以不能删除已经插入的数据(Counting Bloom Filter将每个位扩展为可计数的结构,所以可以应对删除操作);

  • 实现难点在于如果根据N个待插入元素,决定位数组大小M,以及K个独立Hash函数。如果在错误率不大于E的情况下,M至少为 N*lg(1/E)*lge(lg以2为底,e是自然常数,所以lge大约为1.44);当Hash函数个数为ln2*(M/N)的时候,期望错误率最小;
  • 将利用数学计算将大范围内的数值映射到小范围的数组中(字符串可以转换为数字),如果数学计算时间足够快,则可在常数时间定位数据的存放位置;

  • 需要解决数据碰撞(Open Hashing在每个slot上挂载链表用于存储位置重复的元素;Closed Hashing利用某种策略将位置重复的元素存储到下一个可用的slot中),所以好的Hash函数非常难找。源自暴雪的Hash函数,一个字符串对应3 个Hash值,一个用于定位而两外两个用于进一步确定同一位置上的字符串是否相同,如果后面两个Hash值不同于相同位置上的字符串则说明不是同一个字符 串,则需要reHash或者进行拉链处理;如果都相同则说明是同一个字符串。同时可以扩大Hash表大小以降低Hash值的重复率;

样例:

 unsigned long HashString(char *lpszFileName, unsigned long dwHashType)
{
unsigned char *key = (unsigned char *)lpszFileName;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch; while(*key != )
{ ch = toupper(*key++); seed1 = cryptTable[(dwHashType << ) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << ) + ;
}
return seed1;
}
int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize)
{
const int HASH_OFFSET = , HASH_A = , HASH_B = ;
int nHash = HashString(lpszString, HASH_OFFSET);
int nHashA = HashString(lpszString, HASH_A);
int nHashB = HashString(lpszString, HASH_B);
int nHashStart = nHash % nTableSize, nHashPos = nHashStart; while (lpTable[nHashPos].bExists)
{ if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos].nHashB == nHashB)
return nHashPos;
else
nHashPos = (nHashPos + ) % nTableSize; if (nHashPos == nHashStart)
break;
} return -; //Error value
}

补充:

  • D-Left-Hashing可尽量将数据分散存储到表的各部分,如2-Left-Hashing将表分成两个相等部分,每个部分对应一个Hash函 数,H1和H2;存储一个新元素的时候,同时计算两个Hash函数得到两个地址H1(key)和H2(key),此时利用某种策略检查哪一个部分的数据负 载较小,就将新数据存入负载较小的一边,最终分散存储数据;

  • HashTable与Array的区别在于存储元素分布的范围,当存储元素分布范围较为集中的时候,使用确定性的Bit Array表明元素是否存在的效率远高于HashTable,1bit就可以独立的确定一个元素是否存在;相反,当存储元素分布范围较广,Bit Array存储需要较大的空间,此时使用Hash函数将分布范围较广的元素映射到相对较小的一个范围内,并存储到对应的HashTable中,在没有 collision的情况下,存储查询时间仍旧为O(1);但问题在于将一个分布较广的集合映射到一个分布较窄的集合中时,肯定会出现不同元素映射到同一 个元素的误判情况;为了减小误判情况发生的概率,使用k个Hash Function将一个元素对应到HashTable上的k个bits;

参考连接:
http://www.cnblogs.com/allensun/archive/2011/02/16/1956532.html
http://hi.baidu.com/hins_pan/blog/item/329c7bd2d48159113bf3cf79.html

最新文章

  1. POJ1637 Sightseeing tour(判定混合图欧拉回路)
  2. js插入拼接链接 --包含可变字段
  3. [原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存
  4. TOGAF培训讲义
  5. Jquey Form 异步提交文件参数并且在http 信息头header中加上一定参数
  6. Android小项目之十 应用程序更新的签名问题
  7. 解决Handler与Activity同步冲突
  8. jQuery 1.6+ 中attr()与prop() 区别
  9. Jconsole: JAVA 监视和管理控制台简介
  10. 安卓MP3播放器开发实例(1)之音乐列表界面
  11. Webpact打包React后端Node+Express
  12. win10- *.msi 软件的安装,比如 SVN安装报2503,2502
  13. AJAX编程实践
  14. 依赖注入容器-- Autofac
  15. HTTP Streaming Architecture HLS 直播点播 HTTP流架构
  16. 请求http页面的相关过程
  17. MySQL 如何查看表的存储引擎
  18. 使用GDB调试gp(转载)
  19. CUDA[3] Samples for accessing shared/global memory
  20. MSF内网渗透 扫描模块

热门文章

  1. Spring注解详细
  2. Swift4 类与继承, 类型转换, 类型判断
  3. Luogu P1233 木棍加工 【贪心/LIS】
  4. 2018SCin tsyzDay2 模拟赛-动态规划(简单的)
  5. Vim 插件的安装
  6. Robot Framework问题汇总...不断更新中
  7. [USACO 2011 Dec Gold] Cow Calisthenics【二分】
  8. Oracle10g的imp命令
  9. Zygote和System进程的启动过程、Android应用进程启动过程
  10. HBase简介(很好的梳理资料) 转