bit_set位图|布隆过滤器

位图

对于海量整形数据的处理,通常是上百个G的代码。

通常有如下的应用:

1. 快速查找某个数据是否在一个集合中
2. 排序 + 去重
3. 求两个集合的交集、并集等
4. 操作系统中磁盘块标记

如果将数据加载到内存中,运用基本数据结构处理,那就需要百G的内存,这是非常庞大的。

例如:要在40亿的无符号整型数据中,判断某个数在不在。

判断在否只需要0或1标记,利用hash直接定址法或hash映射,对每一个整形开辟一个char的空间。简单计算空间利用: 无符号整形的范围是2^32 约有42亿9千万 也就是开辟42亿9千万字节/大约要4G的内存空间......

优化:一个字节有8个bit位,每一个bit位记录0/1标记在否  也就是需要42亿9千万的bit位  计算得需要大约500M的内存

bitset的框架

首先要对数据处理的范围0-N开空间。bitset需要开N/32 + 1的整形来容纳这些数据。(1个整形=32bit)。这里我们用vector容器作为底层。

位图的成员函数有set(将某位置为1) reset(将某位置为0)  test(判断是否存在 1为存在,0为不存在)      flip(翻转指定位)

构造函数

提前开 N/32 + 1的整形空间,并且初始化为全0.

set

1.计算在第i个int的类型

2.计算在该int类型上j的bit位上

3.利用或运算 ,将第j位置为1

 

reset

与set相反,将某一位置为0

1.计算i _bits上

2.计算_bits的jbit位

3.与运算 与上 第j位的0,其它位的全1    ~(1<<j)

test()

得到某一位的标记 移位操作和与操作

filp()

翻转指定位

1.计算i _bits上

2.计算_bits的jbit位

3._bits[i]异或上 1的左移j位

位图的优缺点

优点:
判断海量数据的存在,判断出现次数有极大的优势。

节省空间,速度快。本质就是hash映射

缺点:

只能映射整形对于字符串,浮点型不能存储

布隆过滤器

海量处理数据,哈希表的存储占用太多空间。

位图不适用于字符串类型的处理

所以将hash和位图相结合。布隆提出过滤器

设计思路

将字符串通过hash函数映射到位图上。这时会产生hash冲突。对于位图上,判断字符串的结果可以是在于不在。

判断不在是准确的,因为hash映射上标志为0,就代表没有发生hash冲突,也没有这个字符串。 

判断在是不准确的。会发生hash冲突。多个字符串有可能映射到这个位上。

为了降低发生hash冲突的概率 布隆过滤器降低冲突概率

一个值映射到一个位置,容易误判(将在不在判断为在)。将一个值映射到多个位置,多个位的结果判断一个值,这样的误判的概率会大大降低。

结论

布隆过滤器是无法彻底解决误判问题。一个key值 通过hash函数映射到多个位,只能降低误判的概率,无法去除误判。

hash函数个数和布隆过滤器的长度选择

过小的过滤器所有的bit位均为1,查询任何结构都是“可能存在”,起不到过滤的结果。过滤器的长度直接影响误判的结果,越长的过滤器,发生哈希冲突的概率越小,误判几率越小。

hash函数的个数与key映射到位图上的速度有关,如果个数过多,位图上变为1的速度也越快,很快就发生hash碰撞。如果个数过少,误判的几率会变高。

该图展示hash个数和过滤器长度与误判率的关系

由大佬推导出来的公式

当我们设置hash函数为3个时候

k=3,ln2=0.7  m=n*k*0.7 =4.3n;

所以在hash函数为3时,布隆过滤器的长度大致为插入元素个数的4倍。

布隆过滤器的模拟

框架

布隆过滤器要实现成为一个模板类,因为布隆过滤器插入的元素是不固定的(整形,字符串)。而位图要求是整形的存储。所以通过hash函数将字符串转整形。一般情况下,布隆过滤器用于处理字符串,故在模板参数的处理,默认给string的处理。

假定传入三个hash函数,那么布隆过滤器的长度为插入元素的4倍

hash函数传入三个稳定的默认参数。

hash函数的作用就是把字符串数据转化为整形,便于建立映射关系。如果一个字符串能转化出不同的整形值,那么就有不同的映射位置。所以这里通过BKDRHash\APHash\DJBHash

选用hash冲突概率最优的字符串转化hash函数

字符串转hash文章:

字符串转hash

struct BKDRHash
{
	size_t operator()(const string& key)
	{
		// BKDR
		size_t hash = 0;
		for (auto e : key)
		{
			hash *= 31;
			hash += e;
		}

		return hash;
	}
};

struct APHash
{
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (size_t i = 0; i < key.size(); i++)
		{
			char ch = key[i];
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
			}
		}
		return hash;
	}
};

struct DJBHash
{
	size_t operator()(const string& key)
	{
		size_t hash = 5381;
		for (auto ch : key)
		{
			hash += (hash << 5) + ch;
		}
		return hash;
	}
};

set

插入字符串“猪八戒”,如果hash函数映射出的三个位置分别为 1   4    7,那么这几个位置为1

此时再存入“tencent”,位图就继续发生改变

test 验证某一位

判断某一位在与否;

判断在——必须三个hash函数对应的位置同时为1   不是一定正确

判断不在——有一个hash函数的映射位为0     一定正确

支持删除么

由于布隆过滤器存在冲突,在删除一个元素时,同时也有可能影响其它元素。

是不支持删除的

  • 一种支持删除的方法(计数删除)

将布隆过滤器中的每位bit扩展成一个小的计数器,插入元素时,k个hash函数映射出的值都+1。删除时,给K个映射位都减一。

缺陷:

存在计数回绕

无法真正确定元素是否真在

布隆过滤器的使用场景

可以误判的场景

比如

用户注册名称,需要判断用户的名称是否被用过

这时候如果一个数据不在 ,那么就是准确的。那如果一个名称通过布隆过滤器被判断出在,(实际上不存在),这时候只要通过数据库的再查找。相比于全部再数据库查找,布隆过滤器极大提高效率。

布隆过滤器的优缺点

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

缺点

1. 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再建立一个白名单,存储可能会误判的数据)
2. 不能获取元素本身
3. 一般情况下不能从布隆过滤器中删除元素
4. 如果采用计数方式删除,可能会存在计数回绕问题

gitee:位图和布隆过滤器的模拟实现

参考资料:

详解布隆过滤器的原理,使用场景和注意事项 - 知乎 (zhihu.com)

各种字符串Hash函数 - clq - 博客园 (cnblogs.com)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】用三种方法创建tkinter桌面窗口

Python的tkinter是Python的标准GUI库之一&#xff0c;它是一个开源的、跨平台的GUI工具包&#xff0c;可以用于创建桌面应用程序。 tkinter提供了许多常见的GUI组件&#xff0c;例如按钮、文本框、标签、列表框等等&#xff0c;可以轻松地创建各种类型的桌面应用程序。它还支持…

计算机组成原理-Cache的基本概念和原理

文章目录 存储系统存在的问题Cache的工作原理局部性原理性能分析例题界定何为局部部分问题总结 存储系统存在的问题 增加Cache层来缓和CPU和主存的工作速度矛盾 Cache的工作原理 启动某个程序后&#xff0c;将程序的代码从辅存中取出放入内存中&#xff0c;再从内存中将代码…

ArcGIS中基于人口数据计算人口密度的方法

文章目录 一、密度分析原理二、点密度分析三、线密度分析四、核密度分析一、密度分析原理 密度分析是指根据输入的要素数据集计算整个区域的数据聚集状况,从而产生一个联系的密度表面。通过密度计算,将每个采样点的值散步到整个研究区域,并获得输出栅格中每个像元的密度值。…

电子学会C/C++编程等级考试2023年03月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:数字字符求和 请编写一个程序实现以下功能:从一个字符串中,提取出所有的数字字符即0-9,并作为数求和。 时间限制:1000 内存限制:65536输入 一行字符串,长度不超过100,字符串中不含空格。输出 字符串中所有数字字符作为数…

Java核心知识点整理大全14-笔记

Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全3-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全4-笔记-CSDN博客 Java核心知识点整理大全5-笔记-CSDN博客 Java核心知识点整理大全6…

SpringBoot 2 系列停止维护,Java8 党何去何从?

SpringBoot 2.x 版本正式停止更新维护&#xff0c;官方将不再提供对 JDK8 版本的支持 SpringBoot Logo 版本的新特性 3.2 版本正式发布&#xff0c;亮点包括&#xff1a; 支持 JDK17、JDK21 版本 对虚拟线程的完整支持 JVM Checkpoint Restore&#xff08;Project CRaC&…

2023-11-25 LeetCode每日一题(二叉树中的伪回文路径)

2023-11-25每日一题 一、题目编号 1457.二叉树中的伪回文路径二、题目链接 点击跳转到题目位置 三、题目描述 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值的排列中…

python中模块的创建及引用(import as,import,from)

模块&#xff08;module&#xff09;简介&#xff1a; 1.模块化&#xff0c;模块化指将一个完整的程序分解为一个一个的小模块&#xff0c; 通过将模块组合&#xff0c;来搭建出一个完整的程序 2.不采用模块化就是统一将所有的代码编写到一个文件中&#xff0c;采用 模块化就是…

SpringBoot——LiteFlow引擎框架

优质博文&#xff1a;IT-BLOG-CN 一、LiteFlow 简介 LiteFlow是一个轻量且强大的国产规则引擎框架&#xff0c;可用于复杂的组件化业务的编排领域。帮助系统变得更加丝滑且灵活。利用LiteFlow&#xff0c;你可以将瀑布流式的代码&#xff0c;转变成以组件为核心概念的代码结构…

jQuery实现横版手风琴效果

一、实现效果 当鼠标滑过方块的时候&#xff0c;方块的状态就会发生如下图所示的变化&#xff0c;同理当鼠标滑到其他的方块也会发生同样的效果&#xff0c;不仅大小会改变同时方块的颜色也会跟着发生变化&#xff1a; 二、代码实现 <!DOCTYPE html> <html><h…

Python pandas数据分析

Python pandas数据分析&#xff1a; 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其…

C语言从入门到精通之【表达式和语句】

1 表达式 表达式由运算符和运算对象组成&#xff0c;最简单的表达式一个单独的运算对象。每个表达式都有一个值&#xff0c;并且是根据运算符优先级规定的顺序来执行&#xff0c;以下是一些表达式&#xff1a; 4 -6 421 a*(b c/d)/20 q 5*2 x q % 3 #q > 3 2 语句 语句…

前端web开发学习笔记

JavaWeb 前端Web开发HTMLCSSjavaScript1.JS引入2.JS基础语法3.JS函数4.JS对象 BOMDOM文档对象模型JS事件监听VueVue常用指令Vue的生命周期 AjaxAxios 前端工程化环境准备NodeJS安装和Vue-cli安装vue项目Vue组件库Element组件的使用 Vue路由Nginx打包部署 前端Web开发 HTML 负…

linux rpm安装软件卸载 以卸载mysql为例

查看rpm包 rpm -qa | grep 内容 卸载rpm rpm -e --nodeps rpm名称

使用VC++设计程序:实现常见的三种图像插值算法:最近邻插值,双线性插值,立方卷积插值

图像放大的三种插值算法 获取源工程可访问gitee可在此工程的基础上进行学习。 该工程的其他文章&#xff1a; 01- 一元熵值、二维熵值 02- 图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像以及图像的旋转 03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器 04-…

VSCode 警告:v-on event ‘@toggleClick‘ must be hyphenated

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

【Spring篇】spring核心——AOP面向切面编程

目录 想要彻底理解AOP&#xff0c;我觉得你的先要了解框架的模块化思想&#xff0c;为此先记录框架在讲AOP 什么是java框架&#xff1f;为什么要出现框架&#xff1f; 我总结以下七点来讲述和帮助理解java框架思想 什么是AOP&#xff1f; 如何理解上面这句话呢&#xff1…

【开源】基于Vue+SpringBoot的农家乐订餐系统

项目编号&#xff1a; S 043 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S043&#xff0c;文末获取源码。} 项目编号&#xff1a;S043&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户2.2 管理员 三、系统展示四、核…

Redis面试题:redis做为缓存,数据的持久化是怎么做的?两种持久化方式有什么区别呢?这两种方式,哪种恢复的比较快呢?

目录 面试官&#xff1a;redis做为缓存&#xff0c;数据的持久化是怎么做的&#xff1f; 面试官&#xff1a;这两种持久化方式有什么区别呢&#xff1f; 面试官&#xff1a;这两种方式&#xff0c;哪种恢复的比较快呢&#xff1f; 面试官&#xff1a;redis做为缓存&#xff…

【【Linux编程介绍之关键配置和常用用法】】

Linux编程介绍之关键配置和常用用法 Hello World ! 我们所说的编写代码包括两部分&#xff1a;代码编写和编译&#xff0c;在Windows下可以使用Visual Studio来完成这两部&#xff0c;可以在 Visual Studio 下编写代码然后直接点击编译就可以了。但是在 Linux 下这两部分是分开…