当前位置: 首页 > wzjs >正文

免费网站模板网三亚百度推广公司电话

免费网站模板网,三亚百度推广公司电话,做网站包括什么软件,天津专业网站制作什么是布隆过滤器 对于上一篇提到的位图,他是有一个比较严重的缺陷的,就是只适用于整型。哈希表/红黑树啥事都能搞,但是空间消耗很多,数据量很多的时候,红黑树就用不上了。所以如果是整型的话,就可以使用…

什么是布隆过滤器 

对于上一篇提到的位图,他是有一个比较严重的缺陷的,就是只适用于整型。哈希表/红黑树啥事都能搞,但是空间消耗很多,数据量很多的时候,红黑树就用不上了。所以如果是整型的话,就可以使用位图来解决,但是!不是位图呢???字符串?结构对象?这时候,位图就使不上劲了。

我们其实可以对位图进行变形,这就是布隆这个大佬提出来的这一种概念:

布隆过滤器(Bloom Filter)由 Burton Howard Bloom 于 1970 年提出,是一种紧凑且巧妙的概率型数据结构,专门用于在“海量非整型数据”中高效地判断“某元素一定不存在,或可能存在”。当数据量极大、元素本身不是整数、且内存无法容纳完整哈希表或红黑树时,传统位图无法直接使用,布隆过滤器便成为理想选择。

假设是字符串,就是通过某种哈希算法,将其转化成一个整型值,然后再通过这个整型值取映射到位图上!

但是则时候主要的问题就是哈希冲突,a和b字符串通过哈希算法出来的整型是不同的,但是来了一个c字符串,通过哈希算法转成的整型值是和a哈希算法后的整型值一致的!这就是哈希冲突!这时候也就有误判问题:就是通过位图知道a和b和c都在,但是只有a和b在,c不在的!所以我们判断一个 key 值在不在是不准确的,但是判断一个 key 值不在是准确的! 

那布隆是怎么考量这个问题的呢? 

它的核心思路分两步:

  1. 把任意类型的 key 通过 k 个独立哈希函数映射成 k 个整数;

  2. 将这 k 个整数对应到一张位图中的 k 个比特位并置 1。

插入时,重复上述两步即可完成;查询时,如果这 k 个比特位中有任意一位是 0,便可断言该 key 一定不存在;若全部为 1,则只能说 key 可能存在——存在误判概率(减少冲突,没有解决冲突)。由于布隆过滤器不保存原始值,只标记位,因此无法像哈希表那样解决冲突,而是通过增加哈希函数数量 k 来尽可能降低冲突率。这样,它在保证极高查询效率的同时,也节省了大量内存空间。

猪八戒是在的,但是孙悟空是不在的,但凡有一个位置不在,那么他就是不在! 

关于哈希函数要有几个?位图开多大比较合适?

哈希函数肯定不是越多越好的,太多了的话,就会消耗过多的空间,而且大多是1的冲突的概率也会是直线的上升的。下面其实有一个推导:

布隆过滤器误判率推导


推导过程:

说明:这个比较复杂,涉及概率论、极限、对数运算、求导函数等知识.

假设:

  • m:布隆过滤器的 bit 长度。

  • n:插入过滤器的元素个数。

  • k:哈希函数的个数。

布隆过滤器哈希函数等条件下某个位设置为 1 的概率:\frac{1}{m}

布隆过滤器哈希函数等条件下某个位设置不为 1 的概率:1-\frac{1}{m}

在经过 k 次哈希后,某个位置依旧不为 1 的概率:(1-\frac{1}{m})^k

根据极限公式:

\lim_{m \to \infty} \left(1 - \frac{1}{m}\right)^{-m} = e

\left(1 - \frac{1}{m}\right)^k = \left(\left(1 - \frac{1}{m}\right)^m\right)^{\frac{k}{m}} \approx e^{-\frac{k}{m}}

添加 n 个元素某个位置不置为 1 的概率:

\left(1 - \frac{1}{m}\right)^{kn} \approx {e^{-\frac{kn}{m}}}

添加 n 个元素某个位置置为 1 的概率:

1 - \left(1 - \frac{1}{m}\right)^{kn} \approx 1 - e^{-\frac{kn}{m}}

查询一个元素,k 次 hash 后误判的概率为都命中 1 的概率:

\left(1 - \left(1 - \frac{1}{m}\right)^{kn}\right)^k \approx \left(1 - e^{-\frac{kn}{m}}\right)^k

结论:

布隆过滤器的误判率为:

f(k) = \left(1 - e^{-\frac{kn}{m}}\right)^k = \left(1 - \frac{1}{e^{\frac{kn}{m}}}\right)^k

由误判率公式可知,在 k (哈希函数)一定的情况下,当 n(插入数据) 增加时,误判率增加,m(布隆过滤器的长度) 增加时,误判率减少。

mn 一定,在对误判率公式求导,误判率尽可能小的情况下,可以得到 hash 数个数:

k = \frac{m}{n}ln2 时误判率最低。

期望的误判率 p 和插入数据个数 n 确定的情况下,再把上面的公式带入误判率公式可以得到,通过期望的误判率和插入数据个数 n 得到 bit 长度:

m = -\frac{n \cdot \ln p}{(\ln 2)^2}  


布隆过滤器代码实现

各种字符串Hash函数 - clq - 博客园https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html

下面代码是一个 C++ 实现的布隆过滤器(Bloom Filter)模板类,它使用了三种不同的哈希函数:BKDR、AP 和 DJB。这个布隆过滤器类允许您设置键(插入元素)并测试键(检查元素是否可能存在于集合中)。此外,还提供了一个计算误判概率的方法。

代码中定义了三个哈希函数结构体 HashFuncBKDRHashFuncAPHashFuncDJB,每个结构体都重载了 operator() 来实现特定的哈希算法。

布隆过滤器类 BloomFilter 模板参数包括:

  • N:预计插入的数据个数。

  • X:每个元素使用的哈希函数个数,默认为 5。

  • K:键的类型,默认为 std::string

  • Hash1Hash2Hash3:三个哈希函数类型,默认分别为 HashFuncBKDRHashFuncAPHashFuncDJB

类中的方法包括:

  • Set(const K& key):将键插入布隆过滤器。

  • Test(const K& key):测试键是否可能存在于布隆过滤器中。

  • getFalseProbability():计算并返回理论误判率。

TestBloomFilter1 函数中,创建了一个布隆过滤器实例并插入了一些字符串,然后测试了这些字符串以及一些不在集合中的字符串。

TestBloomFilter2 函数中,进行了更大规模的测试,包括相似字符串和不相似字符串的误判率测试,并与理论误判率进行了比较。

#pragma once
#include<string>
#include"BitSet.h"// BKDR Hash Function 结构体定义
struct HashFuncBKDR
{// BKDR 哈希算法,由 Brian Kernighan 和 Dennis Ritchie 提出// 该算法在《The C Programming Language》一书中展示,Java 字符串哈希也采用此算法size_t operator()(const std::string& s){size_t hash = 0;for (auto ch : s){hash *= 31;hash += ch;}return hash;}
};// AP Hash Function 结构体定义
struct HashFuncAP
{// AP 哈希算法,由 Arash Partow 发明size_t operator()(const std::string& s){size_t hash = 0;for (size_t i = 0; i < s.size(); i++){if ((i & 1) == 0) // 偶数位字符{hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));}else              // 奇数位字符{hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));}}return hash;}
};// DJB Hash Function 结构体定义
struct HashFuncDJB
{// DJB 哈希算法,由 Daniel J. Bernstein 教授发明size_t operator()(const std::string& s){size_t hash = 5381;for (auto ch : s){hash = hash * 33 ^ ch;}return hash;}
};// BloomFilter 类模板定义
template<size_t N,size_t X = 5,class K = std::string,class Hash1 = HashFuncBKDR,class Hash2 = HashFuncAP,class Hash3 = HashFuncDJB>
class BloomFilter
{
public:// 将 key 插入布隆过滤器void Set(const K& key){size_t hash1 = Hash1()(key) % M;size_t hash2 = Hash2()(key) % M;size_t hash3 = Hash3()(key) % M;_bs.set(hash1);_bs.set(hash2);_bs.set(hash3);}// 测试 key 是否可能存在于布隆过滤器中bool Test(const K& key){size_t hash1 = Hash1()(key) % M;if (!_bs.test(hash1)){return false;}size_t hash2 = Hash2()(key) % M;if (!_bs.test(hash2)){return false;}size_t hash3 = Hash3()(key) % M;if (!_bs.test(hash3)){return false;}return true; // 可能存在误判}// 获取公式计算出的误判率double getFalseProbability(){double p = pow((1.0 - pow(2.71, -3.0 / X)), 3.0);return p;}private:// 位图大小,根据预计插入的数据个数 N 和每个元素使用的哈希函数个数 X 计算得出static const size_t M = N * X;// 使用 BitSet 库来实现位图bit::bitset<M> _bs;
};// 测试 BloomFilter 类的函数
void TestBloomFilter1()
{BloomFilter<10> bf;bf.Set("猪八戒");bf.Set("孙悟空");bf.Set("唐僧");std::cout << bf.Test("猪八戒") << std::endl;std::cout << bf.Test("孙悟空") << std::endl;std::cout << bf.Test("唐僧") << std::endl;std::cout << bf.Test("沙僧") << std::endl;std::cout << bf.Test("猪八戒1") << std::endl;std::cout << bf.Test("猪戒八") << std::endl;
}// 另一个测试 BloomFilter 类的函数
void TestBloomFilter2()
{srand(time(0));const size_t N = 1000000;BloomFilter<N> bf;std::vector<std::string> v1;std::string url = "猪八戒";for (size_t i = 0; i < N; ++i){v1.push_back(url + std::to_string(i));}for (auto& str : v1){bf.Set(str);}// v2 跟 v1 是相似字符串集(前缀一样),但是后缀不一样v1.clear();for (size_t i = 0; i < N; ++i){std::string urlstr = url;urlstr += std::to_string(9999999 + i);v1.push_back(urlstr);}size_t n2 = 0;for (auto& str : v1){if (bf.Test(str)) // 误判{++n2;}}std::cout << "相似字符串误判率:" << (double)n2 / (double)N << std::endl;// 不相似字符串集 前缀后缀都不一样v1.clear();for (size_t i = 0; i < N; ++i){std::string urlstr = "孙悟空";urlstr += std::to_string(i + rand());v1.push_back(urlstr);}size_t n3 = 0;for (auto& str : v1){if (bf.Test(str)){++n3;}}std::cout << "不相似字符串误判率:" << (double)n3 / (double)N << std::endl;std::cout << "公式计算出的误判率:" << bf.getFalseProbability() << std::endl;
}
PS D:\2024C语言\C++加餐\c-additional-meal\哈希扩展学习加餐> ./test
相似字符串误判率:0.127968
不相似字符串误判率:0.104435
公式计算出的误判率:0.091236

当然了,我们这里没有动态的去映射,后续我们可以更好的完善这个布隆过滤器! 

布隆过滤器删除问题

布隆过滤器默认是不支持删除的,因为例如“猪八戒”和“孙悟空”都映射在布隆过滤器中,他们映射的位有一个位是共同映射的(冲突的),如果我们把孙悟空删掉,那么再去查找“猪八戒”会查找不到,因为那么“猪八戒”间接被删掉了。

解决方案:可以考虑引用计数/计数标记的方式,一个位置用多个位标记,记录映射这个位的计数值,删除时,仅仅减减计数,那么就可以某种程度支持删除。但是这个方案也有缺陷,如果一个值不在布隆过滤器中,我们去删除,减减了映射位的计数,那么会影响已存在的值,也就是说,一个确定存在的值,可能会变成不存在,这里就很坑,因为在极端情况下,我们是使用了Test去判断在不在,但是可能会误判啊!!!当然也有人提出,我们可以考虑计数方式支持删除,但是定期重建一下布隆过滤器,这样也是一种思路。

布隆过滤器的应用

首先我们分析一下布隆过滤器的优缺点:

优点:

  • 效率高,节省空间,相比位图,可以适用于各种类型的标记过滤。

缺点:

  • 存在误判(在是不准确的,不在是准确的)。

  • 不好支持删除。

布隆过滤器在实际中的一些应用:

  • 爬虫系统中URL去重: 在爬虫系统中,为了避免重复爬取相同的URL,可以使用布隆过滤器来进行URL去重。爬取到的URL可以通过布隆过滤器进行判断,已经存在的URL则可以直接忽略,避免重复的网络请求和数据处理。(因为有时候会有环形网站的存在,可能存在死循环)

  • 垃圾邮件过滤: 在垃圾邮件过滤系统中,布隆过滤器可以用来判断邮件是否是垃圾邮件。系统可以将已知的垃圾邮件的特征信息存储在布隆过滤器中,当新的邮件到达时,可以通过布隆过滤器快速判断是否为垃圾邮件,从而提高过滤的效率。

  • 预防缓存穿透: 在分布式缓存系统中,布隆过滤器可以用来解决缓存穿透的问题。缓存穿透是指恶意用户请求一个不存在的数据,导致请求直接访问数据库,造成数据库压力过大。布隆过滤器可以先判断请求的数据是否存在于布隆过滤器中,如果不存在,直接返回不存在,避免对数据库的无效查询。类似redis就是缓存!对热数据的中间层的缓存!

  • 对数据库查询提效: 在数据库中,布隆过滤器可以用来加速查询操作。例如:一个app要快速判断一个电话号码是否注册过,可以使用布隆过滤器来判断一个用户电话号码是否存在于表中,如果不存在,可以直接返回不存在,避免对数据库进行无用的查询操作。如果在,再去数据库查询进行二次确认。

布隆过滤器其实应用听广泛的!!!

http://www.dtcms.com/wzjs/127210.html

相关文章:

  • 做survey的网站百度收录网站入口
  • 旅游营销网站建设微信scrm
  • 西樵网站建设公司产品设计
  • 房地产销售人员网站怎么做南宁seo结算
  • 开发一个小程序大概要多少钱seo有哪些优缺点?
  • 2017网站建设报价单在线友情链接
  • 网站运营管理报告总结网络整合营销策划书
  • 时尚网站策划专业做网站
  • 网站注册好域名怎么办成都网络营销品牌代理机构
  • 徐州金网网站建设最彻底的手机优化软件
  • 怎么在建设银行网站更新身份证做个电商平台要多少钱
  • 泽成seo网站排名百度快速优化推广
  • 动漫制作专业能选择什么职业南宁seo公司哪家好
  • 做网站公司的使命我赢网客服系统
  • 如何自己免费建网站seo常用分析的专业工具
  • 做外贸网站价位发布平台
  • 跨境电商网站制作太原推广团队
  • 做网站需不需要云数据库搜索推广开户
  • 北京网站建设及优化外贸独立站怎么建站
  • 有做微信婚介网站的吗产品宣传方式有哪些
  • 南京建网站公司视频专用客户端app
  • 朔州如何做百度的网站外链群发平台
  • 网站开发新功能产品推广方案范文
  • 中国十大网络营销公司以下哪个单词表示搜索引擎优化
  • 用网站做淘客怎么做百姓网
  • 韩国购物网站推广管理
  • 科学城做网站公司品牌营销策划书
  • 成品网站建设哪家好pc网站优化排名
  • 官方网站建设的方法有哪些方面产品推广方法
  • php语言做购物网站免费自学电商教程