布隆过滤器

末蓝、 2022-06-12 22:14 413阅读 0赞

布隆过滤器实际上就是哈希和位图的结合
它的优点:速度快并且节省空间
它的缺点:存在误判(比如存在不同的字符串可能存在相同的ASCII,这样我们在判断的时候就会出现误判)
这样的误判一定是发生在 判断它存在的情况下
误判一定不会发生在 不存在的情况下
为了降低误判率,我们必须尽可能的减少哈希冲突
也就是一个Key值可以有多个映射的位置

  1. #include<iostream>
  2. #include<stdlib.h>
  3. #include<string>
  4. #include"BitMap.h"
  5. using namespace std;
  6. template<class K>
  7. struct _HashFunc1
  8. {
  9. size_t BKDRHash(const char *str)
  10. {
  11. register size_t hash = 0;
  12. while (size_t ch = (size_t)*str++)
  13. {
  14. hash = hash * 131 + ch; // 也可以乘以31、131、1313、13131、131313..
  15. }
  16. return hash;
  17. }
  18. size_t operator()(const string &s)
  19. {
  20. return BKDRHash(s.c_str());
  21. }
  22. };
  23. template<class K>
  24. struct _HashFunc2
  25. {
  26. size_t SDBMHash(const char *str)
  27. {
  28. register size_t hash = 0;
  29. while (size_t ch = (size_t)*str++)
  30. {
  31. hash = 65599 * hash + ch;
  32. //hash = (size_t)ch + (hash << 6) + (hash << 16) - hash;
  33. }
  34. return hash;
  35. }
  36. size_t operator()(const string &s)
  37. {
  38. return SDBMHash(s.c_str());
  39. }
  40. };
  41. template<class K>
  42. struct _HashFunc3
  43. {
  44. size_t RSHash(const char *str)
  45. {
  46. if (!*str) // 这是由本人添加,以保证空字符串返回哈希值0
  47. return 0;
  48. register size_t hash = 1315423911;
  49. while (size_t ch = (size_t)*str++)
  50. {
  51. hash ^= ((hash << 5) + ch + (hash >> 2));
  52. }
  53. return hash;
  54. }
  55. size_t operator()(const string &s)
  56. {
  57. return RSHash(s.c_str());
  58. }
  59. };
  60. template<class K>
  61. struct _HashFunc4
  62. {
  63. size_t RSHash(const char *str)
  64. {
  65. register size_t hash = 0;
  66. size_t magic = 63689;
  67. while (size_t ch = (size_t)*str++)
  68. {
  69. hash = hash * magic + ch;
  70. magic *= 378551;
  71. }
  72. return hash;
  73. }
  74. size_t operator()(const string&s)
  75. {
  76. return RSHash(s.c_str());
  77. }
  78. };
  79. template<class K>
  80. struct _HashFunc5
  81. {
  82. size_t RSHash(const char *str)
  83. {
  84. register size_t hash = 0;
  85. size_t ch;
  86. for (long i = 0; ch = (size_t)*str++; i++)
  87. {
  88. if ((i & 1) == 0)
  89. {
  90. hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
  91. }
  92. else
  93. {
  94. hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
  95. }
  96. }
  97. return hash;
  98. }
  99. size_t operator()(const string &s)
  100. {
  101. return RSHash(s.c_str());
  102. }
  103. };
  104. template<class K=string,typename HashFun1=_HashFunc1<K>,
  105. typename HashFun2 = _HashFunc2<K>,
  106. typename HashFun3 = _HashFunc3<K>,
  107. typename HashFun4 = _HashFunc4<K>,
  108. typename HashFun5 = _HashFunc5<K>>
  109. class BloomFiler
  110. {
  111. public:
  112. BloomFiler(size_t n)
  113. :_bp(n*5*2)
  114. , _range(n*5*2)
  115. {
  116. }
  117. void Set(const K&key)
  118. {
  119. size_t Hash1 = HashFun1()(key);
  120. size_t Hash2 = HashFun2()(key);
  121. size_t Hash3 = HashFun3()(key);
  122. size_t Hash4 = HashFun4()(key);
  123. size_t Hash5 = HashFun5()(key);
  124. _bp.Set(Hash1%_range);
  125. _bp.Set(Hash2%_range);
  126. _bp.Set(Hash3%_range);
  127. _bp.Set(Hash4%_range);
  128. _bp.Set(Hash5%_range);
  129. }
  130. bool Test(const K&key)
  131. {
  132. size_t Hash1 = HashFun1()(key);
  133. if (_bp.Test(Hash1%_range) == false)
  134. {
  135. return false;
  136. }
  137. size_t Hash2 = HashFun2()(key);
  138. if (_bp.Test(Hash2%_range) == false)
  139. {
  140. return false;
  141. }
  142. size_t Hash3 = HashFun3()(key);
  143. if (_bp.Test(Hash3%_range) == false)
  144. {
  145. return false;
  146. }
  147. size_t Hash4 = HashFun4()(key);
  148. if (_bp.Test(Hash4%_range) == false)
  149. {
  150. return false;
  151. }
  152. size_t Hash5 = HashFun5()(key);
  153. if (_bp.Test(Hash5%_range) == false)
  154. {
  155. return false;
  156. }
  157. return true;
  158. }
  159. protected:
  160. BitMap _bp;
  161. size_t _range;
  162. };
  163. int main()
  164. {
  165. BloomFiler<>bf(500);
  166. string s1 = "child";
  167. string s2 = "qqild";
  168. string s3 = "eeild";
  169. string s4 = "ddild";
  170. bf.Set(s1);
  171. bf.Set(s2);
  172. bf.Set(s3);
  173. bf.Set(s4);
  174. cout<<bf.Test(s1)<<endl;
  175. cout << bf.Test(s2) << endl;
  176. cout << bf.Test(s3) << endl;
  177. cout << bf.Test(s4) << endl;
  178. system("pause");
  179. return 0;
  180. }

但是这样的布隆过滤器不支持删除操作,因为可能会影响其他位置上的元素
因此为了支持删除操作将其修改成为引用计数版本的但是这样做必须要来维护引用计数,使用数组来存放引用计数,不再涉及位运算,因此这样做实际上去除了布隆过滤器原本节省空间的优势。

  1. #include<iostream>
  2. #include<stdlib.h>
  3. #include<vector>
  4. #include<string>
  5. #include"BitMap.h"
  6. using namespace std;
  7. template<class K>
  8. struct _HashFunc1
  9. {
  10. size_t BKDRHash(const char *str)
  11. {
  12. register size_t hash = 0;
  13. while (size_t ch = (size_t)*str++)
  14. {
  15. hash = hash * 131 + ch; // 也可以乘以31、131、1313、13131、131313..
  16. }
  17. return hash;
  18. }
  19. size_t operator()(const string &s)
  20. {
  21. return BKDRHash(s.c_str());
  22. }
  23. };
  24. template<class K>
  25. struct _HashFunc2
  26. {
  27. size_t SDBMHash(const char *str)
  28. {
  29. register size_t hash = 0;
  30. while (size_t ch = (size_t)*str++)
  31. {
  32. hash = 65599 * hash + ch;
  33. //hash = (size_t)ch + (hash << 6) + (hash << 16) - hash;
  34. }
  35. return hash;
  36. }
  37. size_t operator()(const string &s)
  38. {
  39. return SDBMHash(s.c_str());
  40. }
  41. };
  42. template<class K>
  43. struct _HashFunc3
  44. {
  45. size_t RSHash(const char *str)
  46. {
  47. if (!*str) // 这是由本人添加,以保证空字符串返回哈希值0
  48. return 0;
  49. register size_t hash = 1315423911;
  50. while (size_t ch = (size_t)*str++)
  51. {
  52. hash ^= ((hash << 5) + ch + (hash >> 2));
  53. }
  54. return hash;
  55. }
  56. size_t operator()(const string &s)
  57. {
  58. return RSHash(s.c_str());
  59. }
  60. };
  61. template<class K>
  62. struct _HashFunc4
  63. {
  64. size_t RSHash(const char *str)
  65. {
  66. register size_t hash = 0;
  67. size_t magic = 63689;
  68. while (size_t ch = (size_t)*str++)
  69. {
  70. hash = hash * magic + ch;
  71. magic *= 378551;
  72. }
  73. return hash;
  74. }
  75. size_t operator()(const string&s)
  76. {
  77. return RSHash(s.c_str());
  78. }
  79. };
  80. template<class K>
  81. struct _HashFunc5
  82. {
  83. size_t RSHash(const char *str)
  84. {
  85. register size_t hash = 0;
  86. size_t ch;
  87. for (long i = 0; ch = (size_t)*str++; i++)
  88. {
  89. if ((i & 1) == 0)
  90. {
  91. hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
  92. }
  93. else
  94. {
  95. hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
  96. }
  97. }
  98. return hash;
  99. }
  100. size_t operator()(const string &s)
  101. {
  102. return RSHash(s.c_str());
  103. }
  104. };
  105. template<class K = string, typename HashFun1 = _HashFunc1<K>,
  106. typename HashFun2 = _HashFunc2<K>,
  107. typename HashFun3 = _HashFunc3<K>,
  108. typename HashFun4 = _HashFunc4<K>,
  109. typename HashFun5 = _HashFunc5<K >>
  110. class BloomFilerRef
  111. {
  112. public:
  113. BloomFilerRef(const int&n)
  114. : _range(n * 5 * 2)
  115. {
  116. _v.resize(n * 5 * 2);
  117. }
  118. void Set(const K&key)
  119. {
  120. size_t Hash1 = HashFun1()(key)%_range;
  121. _v[Hash1]++;
  122. size_t Hash2 = HashFun2()(key) % _range;
  123. _v[Hash2]++;
  124. size_t Hash3 = HashFun3()(key) % _range;
  125. _v[Hash3]++;
  126. size_t Hash4 = HashFun4()(key) % _range;
  127. _v[Hash4]++;
  128. size_t Hash5 = HashFun5()(key) % _range;
  129. _v[Hash5]++;
  130. }
  131. void Reset(const K&key)
  132. {
  133. size_t Hash1 = HashFun1()(key) % _range;
  134. _v[Hash1]--;
  135. size_t Hash2 = HashFun2()(key) % _range;
  136. _v[Hash2]--;
  137. size_t Hash3 = HashFun3()(key) % _range;
  138. _v[Hash3]--;
  139. size_t Hash4 = HashFun4()(key) % _range;
  140. _v[Hash4]--;
  141. size_t Hash5 = HashFun5()(key) % _range;
  142. _v[Hash5]--;
  143. }
  144. bool Test(const K&key)
  145. {
  146. size_t Hash1 = HashFun1()(key) % _range;
  147. if (_v[Hash1] == false)
  148. {
  149. return false;
  150. }
  151. size_t Hash2 = HashFun1()(key) % _range;
  152. if (_v[Hash2] == false)
  153. {
  154. return false;
  155. }
  156. size_t Hash3 = HashFun1()(key) % _range;
  157. if (_v[Hash3] == false)
  158. {
  159. return false;
  160. }
  161. size_t Hash4 = HashFun1()(key) % _range;
  162. if (_v[Hash4] == false)
  163. {
  164. return false;
  165. }
  166. size_t Hash5 = HashFun1()(key) % _range;
  167. if (_v[Hash5] == false)
  168. {
  169. return false;
  170. }
  171. return true;
  172. }
  173. protected:
  174. vector<size_t>_v;
  175. size_t _range;
  176. };

发表评论

表情:
评论列表 (有 0 条评论,413人围观)

还没有评论,来说两句吧...

相关阅读

    相关 过滤器

    布隆过滤器 什么是布隆过滤器? 布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的`二进制向量`和`一系列随机映射函数`。布

    相关 过滤器

    > 布隆过滤器\[1\](Bloom Filter)是由布隆在1970年提出的。它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一

    相关 过滤器

    布隆过滤器实际上就是哈希和位图的结合 它的优点:速度快并且节省空间 它的缺点:存在误判(比如存在不同的字符串可能存在相同的ASCII,这样我们在判断的时候就会出现误判)

    相关 过滤器

    布隆过滤器原理 布隆过滤器有什么用? 布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。 特

    相关 过滤器

    布隆过滤器介绍 > 布隆过滤器在wiki上的介绍: 布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布

    相关 过滤器

    布隆过滤器常常被用来检测某个元素是否是巨量数据集合中的成员 1、基本原理: (1)将长度为m的位数组元素全部置为0; (2)对集合S中的某个成员a,分别用k个哈希函数对其