哈希的应用:布隆过滤器(C++实现)

news2024/9/26 5:24:46

文章目录

  • 1. 布隆过滤器
    • 1.1 背景
    • 1.2 概念
    • 1.3 控制误判率
  • 2. 实现布隆过滤器
    • 2.1 布隆过滤器类
    • 2.2 Set
    • 2.3 Test
    • 2.4 删除
  • 3. 优点
  • 4. 缺陷
  • 4. 缺陷

1. 布隆过滤器

1.1 背景

位图(bitmap算法)告诉我们,想判断一个元素是否存在于某个集合中,如果数据量少,使用搜索树和哈希表是非常快速的。但是一旦元素个数从亿级起步,所需要的内存空间就不足以让这些数据结构发挥作用。位图用一个比特位的0和1表示元素的状态,极大地提高了空间利用率。

然而,位图最大的缺陷是它只能处理整型值,而实际上常常以字符串为key值存储数据,有的人会说,用大佬写的字符串转整型的哈希算法不就好了?结合以前学过的哈希算法,一个字符(char)有256种情况,就算字符是常用的26个英文字母,那它也比数字字符10种情况多。从原理上看,不论通过如何巧妙的哈希函数,字符串转整型发生哈希冲突是不可避免的。

我们一定经历过“该用户名已被占用”这样的场景,常常是输入的过程或者输完一会(甚至不用按回车)就在旁边提示你“已被占用”,这个功能就用到了布隆过滤器。

除此之外,还可以用过滤垃圾网站来理解布隆过滤器:

在黑名单内的垃圾网站毕竟是少数,如果每次都在黑名单里查找,效率太低了,所以可以在数据库之前加上一个布隆过滤器,如果垃圾网站在过滤器中,才会继续在数据库中搜索,这样不在黑名单中的垃圾网站就被过滤掉了。

1.2 概念

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询。它是位图的优化版本,哈希冲突既然不能避免,那我们就尽量减少出现冲突带来的误判情况。

什么是“冲突带来的误判情况”?

首先,布隆过滤器为了减少哈希冲突(注意是冲突而不是冲突带来的误判),使用了多个哈希函数,将多个位置的比特位设置为1,每一个key值都能用几个比特位表示它的状态。

如何判断一个元素是否存在?

  • 只要它的所有哈希函数得到的比特位上都已经被设置为1,则说明它有可能已经存在。

至于为什么说有可能,请看下面的分析。

image-20221216171659052

像这样就不算误判,因为即使苹果的2、3和香蕉的1、2共用了同一个位置,但是苹果的1和香蕉的3是不同位置,它们就不会构成误判情况。所以真正标识苹果和香蕉是否存在的哈希函数是1和3。

image-20221216172004601

葡萄的每一个哈希函数得出的位置都已经被占用了,但显然它们是被不同元素占用了,而集合中并没有葡萄这个元素,这就是冲突带来的误判情况。

1.3 控制误判率

从原理上,误判情况出现的次数也是不可避免的,只能降低可能性。它取决于两个方面:

  • 哈希函数的个数:哈希函数越多,标识一个元素的哈希函数组合也就越多,出现误判率的可能性越小;
  • 总比特位的个数:决定了哈希函数发生哈希冲突的概率。

但是,它们之间也必须达到平衡,因为哈希函数的个数越多,多次计算会导致效率降低,而布隆过滤器的长度太长也会影响效率。

有人给出了哈希函数个数和布隆过滤器长度在保证效率的情况下最均衡的关系:
m = − ( n l n p ) / ( l n 2 ) 2 m = - (nlnp)/(ln2)^2 m=(nlnp)/(ln2)2

k = ( m / n ) l n 2 k = (m/n)ln2 k=(m/n)ln2

其中:

  • k:哈希函数个数;
  • m:布隆过滤器长度;
  • n:插入的元素个数;
  • p:误判率。

当哈希函数个数k=3时,取 l n 2 ln2 ln2=0.7,可以得出布隆过滤器长度m和插入元素个数n之间的关系:m=4n,即布隆过滤器长度为插入元素个数4倍。

2. 实现布隆过滤器

2.1 布隆过滤器类

  • 首先底层用STL中的bitset容器实现,所以需要模板参数N,用于规定布隆过滤器长度。

  • 由于处理的数据类型不一定每次都是字符串类型,所以用模板参数K表示,而字符串类型又是常客,所以赋予数据类型模板参数K以缺省值为string类型。

  • 其次模板参数中还要添加3个哈希函数,都各自缺省地赋予处理string类型的哈希函数。

template<size_t N,
class K = string, class Hash1 = BKDRHash, class Hash2 = APHash, class Hash3 = DJBHash>
class BloomFilter
{
	// ...
private:
	bitset<N> _bs;
};

由于K的缺省值是string,所以默认的哈希函数也要是处理字符串的。

BKDRHash、APHash和DJBHash是个最有效的哈希函数,它们都使用仿函数实现:

struct BKDRHash
{
	size_t operator()(const string& s)
	{
		size_t value = 0;
		for (auto ch : s)
		{
			value = value * 131 + ch;
		}
		return value;
	}
};
struct APHash
{
	size_t operator()(const string& s)
	{
		size_t value = 0;
		for (size_t i = 0; i < s.size(); i++)
		{
			if ((i & 1) == 0)
			{
				value ^= ((value << 7) ^ s[i] ^ (value >> 3));
			}
			else
			{
				value ^= (~((value << 11) ^ s[i] ^ (value >> 5)));
			}
		}
		return value;
	}
};
struct DJBHash
{
	size_t operator()(const string& s)
	{
		if (s.empty())
			return 0;
		size_t value = 5381;
		for (auto ch : s)
		{
			value += (value << 5) + ch;
		}
		return value;
	}
};

2.2 Set

  • Set:插入元素到布隆过滤器中。

插入元素时,需要通过三个哈希函数分别计算出元素对应的三个比特位的序号,然后复用bitset的set接口将位图中的这三个比特位设置为1即可。

void Set(const K& key)
{
    size_t hash1 = Hash1()(key) % N;
    size_t hash2 = Hash2()(key) % N;
    size_t hash3 = Hash3()(key) % N;

    _bs.set(hash1);
    _bs.set(hash2);
    _bs.set(hash3);
}

2.3 Test

  • Test:查找某个元素是否在某个集合中。

同样地,通过三个哈希函数分别计算出元素对应的三个比特位的序号,然后复用bitset的test接口,判断位图中的这三个比特位是否被设置为1。

  • 只要三个比特位中有一个比特位未被设置为1则说明该元素一定不存在;
  • 如果三个比特位全部被设置,返回true。

注意:

三个比特位全部被设置为1并不代表这个元素一定存在于这个集合中,以最开始的葡萄例子就可以知道,不过经过两层的优化(哈希函数减少冲突,多个哈希函数减少误判),误判率已经很低了。

也就是说:

  • 返回false,不存在就是一定不存在,是准确的;
  • 返回true,存在不是100%存在吗,可能存在误判。
bool Test(const K& key)
{
    size_t hash1 = Hash1()(key) % N;
    if (_bs.test(hash1) == false)
    {
        return false;				// 准确
    }

    size_t hash2 = Hash2()(key) % N;
    if (_bs.test(hash2) == false)
    {
        return false;				// 准确
    }

    size_t hash3 = Hash3()(key) % N;
    if (_bs.test(hash3) == false)
    {
        return false;				// 准确
    }

    return true;					// 可能误判
}

2.4 删除

布隆过滤器一般不支持删除操作:

  1. 首先从原理上删除操作会直接影响哈希函数的结果,那么每一次删除都要重新把这个容器中的所有元素重新再映射一遍,影响了其他元素,降低效率。
  2. 其次布隆过滤器要删除一个元素,首先要保证它是真正存在这个集合中的,但是误判是无法避免的,所以删除有一定的风险。

要让布隆过滤器支持删除,必须要满足:

  1. 为每一个比特位增加一个引用计数,当在一个位置上增加一个元素,引用计数+1,反之-1,这样删除就不会改变布隆过滤器的长度,也就不会影响其他元素。但是这违背了布隆过滤器(位图)本身的应用场景:省空间+快速查询。

  2. 当使用Test接口得知元素可能存在于映射以后的布隆过滤器中,再进一步去原始文件验证这个元素是否存在于集合中。但这就像从内存中突然跳到磁盘文件中查找,文件IO和磁盘IO相对于内存而言是很慢的,所以还是降低了效率。

结合上面两点,再加上布隆过滤器本身的应用就是为了查询,而删除对它而言不痛不痒,因为位图这个容器是直接在内存中操作比特位的,即使有很多剩下的没用的元素,对计算机而言它也只是几个比特位,这是无关痛痒的。

3. 优点

  • 增加和查询元素的时间复杂度为O(K)(K为哈希函数的个数,一般比较小),与数据量大小无关。
  • 哈希函数相互之间没有关系,方便硬件并行运算。
  • 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势。
  • 在能够承受一定的误判时,布隆过滤器比其他数据结构有着很大的空间优势。
  • 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能。
  • 使用同一组哈希函数的布隆过滤器可以进行交、并、差运算。

4. 缺陷

  • 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再自建一个白名单,存储可能会误判的数据)
  • 不能获取元素本身。
    本身,在某些对保密要求比较严格的场合有很大优势。
  • 在能够承受一定的误判时,布隆过滤器比其他数据结构有着很大的空间优势。
  • 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能。
  • 使用同一组哈希函数的布隆过滤器可以进行交、并、差运算。

4. 缺陷

  • 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再自建一个白名单,存储可能会误判的数据)
  • 不能获取元素本身。
  • 一般情况下不能从布隆过滤器中删除元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言指针 字符 字符串

1、sizeof 某个类型或者某个变量在内存中占用字节数。 例如&#xff1a;sizeof(int) ; sizeof(i)&#xff1b;都可以使用 2、运算符& 获取变量的地址。 int i; scanf("%d",&i); 输入变量时&#xff0c;必须使用&运算符。 &操作符只能应…

机器学习100天(二):002 数据预处理之导入数据集

机器学习 100 天,今天讲的是:数据预处理之导入数据集。 首先,我们打开 spyder。新建一个 load_data.py 脚本。 第一步,导入标准库 机器学习常用的标准库有 3 个: 第一个:numpy,用于数据处理。 第二个:matplotlib.pyplot,用于画图。 第三个:pandas,用于数值分析…

python 爬虫

前言 一、什么是爬虫 爬虫&#xff1a;&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在 FOAF 社区中间&#xff0c;更经常地称为网页追逐者&#xff09;&#xff1b;它是一种按照一定的规则&#xff0c;自动地从互联网上抓取对于我们有价值的网络信息的程序…

最强大的布局方案——网格Grid布局万字详解

Grid 布局又称网格布局&#xff0c;是W3C提出的一个二维布局系统&#xff0c;它与 Flex 布局有一定的相似性&#xff0c;都可以指定容器内部多个项目的位置。但它们也存在重大区别。Flex 布局是轴线布局&#xff0c;只能指定"项目"针对轴线的位置&#xff0c;可以看作…

jsp+ssm计算机毕业设计大学城二手书交易网站【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

绝对神器,今天教你如何识别图片上竖排的日语文字

在文字翻译或者其他的工作中我们经常遇到竖排的日语&#xff0c;有时候我们用普通的日语识别的软件根本无法完成 这个时候我们就需要一款可以识别竖排的日语工具&#xff0c;横排的我们很容易就能找到&#xff0c;但是竖排的就无能为力了 今天我们讲下如何识别竖排日语识别&a…

ZERO-SHOT:多聚焦融合

ZERO-SHOT MULTI-FOCUS IMAGE FUSION &#xff08;零镜头多焦点图像融合&#xff09; 多聚焦图像融合 (Multi-focus image fusion (MFIF)) 是消除成像过程中产生的离焦模糊的有效方法。The difficulties in focus level estimation and the lack of real training set for su…

计算机毕业设计springboot+vue文体用品商城网站

项目介绍 在当今社会的高速发展过程中,产生的劳动力越来越大,提高人们的生活水平和质量,尤其计算机科技的进步,数据和信息以人兴化为本的目的,给人们提供优质的服务,其中网上购买商品尤其突出,使我们的购物方式发生巨大的改变。而线上购物,不仅需要在硬件上为人们提供服务网上购…

ASPICE详细介绍-3.ASPICE有多少能力等级?

目录ASPICE有多少能力等级&#xff1f;9 个过程属性过程属性评定过程能力等级模型ASPICE有多少能力等级&#xff1f; ASPICE能力等级从0级到5级共分为6个层次&#xff0c;必须满足前一级别才可晋级下一个级别的评估。 【0级】Incomplete&#xff0c;未完成。 The process is…

【YOLOv7-环境搭建】PyTorch安装后输出版本显示No module named ‘Torch’的解决方法

可能一&#xff1a;PyCharm环境导入错误 配置的解释器&#xff0c;必须为所创建的虚拟环境下的python.exe文件&#xff0c;别的路径下的python.exe文件不好使&#xff01;&#xff01; 解决方法&#xff1a;根据【YOLOv7-环境搭建③】PyCharm安装和环境、解释器配置文中配置解…

微信小程序自定义头部导航nav

1.封装自定义nav导航组件 // app.js App({globalData: {systeminfo: false, //系统信息headerBtnPosi: false //头部菜单高度} })// components/nav/nav.js const app getApp(); Component({properties: {vTitle: { // 标题type: String,value: ""},isSearch: {…

大厂频频裁员,0基础转行做IT是不是已经晚了

现在转行做程序员是不是已经晚了 转行不会晚&#xff0c;晚的是你数不清的犹豫 对于二十来岁刚毕业或者毕业没几年的人来说&#xff0c;经历过社会的“摧残”&#xff0c;面对着一眼能够望到头的工作&#xff0c;拿着也不太高的工资&#xff0c;总是会去寻求一些改变与其每天…

Ajax请求原理与数据抓取

有些时候&#xff0c;我们直接通过网络请求库请求网页地址时&#xff0c;得到的响应结果可能跟浏览器中右键查看网页源码所看到的内容不一样。例如&#xff0c;在抓取&#xff1a;https://www.feeair.com/threeCode.html &#xff08;飞啊网&#xff09;这个网页时&#xff0c;…

公司固定资产管理系统

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 模块划分&#xff1a;公告类型、公告信息、员工信息、仓库信息、资产类型、资产信息、供应商信 息、采购信息、盗产调拨…

(Matlab)基于蝙蝠算法实现电力系统经济调度

目录 摘要&#xff1a; 1.蝙蝠优化算法的基本原理&#xff1a; 2.蝙蝠优化算法的流程&#xff1a; 3.仿真实验分析&#xff1a; 摘要&#xff1a; 基于Matalb平台&#xff0c;构建基于蝙蝠活动行为的蝙蝠优化算法&#xff0c;对一个含有6个火电机组的电力系统进行优化调度…

毕业设计 ESP32在线墨水屏桌面摆件 -物联网 单片机 嵌入式

0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过…

单因子分析(如何判定一个因子是否有效)

本人之前都是做期权中性策略&#xff0c;第一次接触这个多因子策略&#xff0c;和一些大私募对接学习后&#xff0c;才知道这里面的水&#xff08;只能说各有各的道&#xff09;。 先说下&#xff0c;何为因子策略&#xff0c;就是一个因子和股票的价格在一定时间内是存在一定的…

【算法数据结构专题】「线程锁算法专项」初探CLH队列锁机制原理分析

技术扩展 SMP&#xff08;对称多处理器架构&#xff09; SMP(Symmetric Multi-Processor)&#xff0c;即对称多处理器结构&#xff0c;指服务器中多个CPU对称工作&#xff0c;每个CPU访问内存地址所需时间相同。其主要特征是共享&#xff0c;包含对CPU&#xff0c;内存&#…

使用Python互转pdf文档和word文档

1 前言 一日&#xff0c;欲将手头上的一份pdf文档转换成word文档。先试着用XX办公软件试了下&#xff0c;微信扫码登录后&#xff0c;在PDF转换界面&#xff0c;选中文档&#xff0c;点击“开始转换”&#xff0c;弹出提示对话框&#xff1a;免费的只给转换5页文档&#xff0c…

十万部冷知识:本届世界杯阿根廷会夺冠吗?

明天&#xff0c;世界杯的决赛“阿法大战”就开始了。而我个人是希望阿根廷夺冠的&#xff0c;熟悉我的人会知道&#xff0c;在2014巴西世界杯的64场比赛中&#xff0c;我曾预测对了63场&#xff0c;唯一一场不对的就是&#xff0c;那年阿根廷和德国的决赛&#xff0c;我当时就…