位图和布隆过滤器的实现

news2024/12/30 2:17:49

前言

        位图和布隆过滤器是基于哈希思想实现的数据结构,他们在很多的方面都有应用,比如:操作系统中的磁盘标记,快速查找某个数据是否在集合中。布隆过滤器可以高效的进行插入和查询,可以告诉你“某样东西一定不存在或者可能存在”。让我们一起来认识一下它们吧。

1.位图

        1.1位图的概念

        所谓位图就是用每一位来存放某种状态,适用于海量数据处理,数据无重复的场景。通过用于判断某个数据在不在。 

        1.2位图的实现

        

#include<vector>
using namespace std;
namespace qyy
{

	class BitSet//位图
	{
	public:
		BitSet(size_t N)
		{
			_array.resize(N / 32 + 1, 0);//开空间并初始化为全0
			int _num = 0;//位图中保存的数据个数
		}
		void set(int x)//将数据x加入位图
		{
			int index = x / 32;//求出x在第几个位置
			int pos = x % 32;//求出是x是第几位
			_array[index] |= (1 << pos);//将数据x加入到位图中
			++_num;
		}
		void reset(int x)//将位图中的x取消
		{
			int index = x / 32;//求出x在第几个位置
			int pos = x % 32;//求出是x是第几位
			_array[index] &= ~(1 << pos);//将数据从位图中取出
			--_num;
		}
		bool test(int x)//判断x是否在位图中
		{
			int index = x / 32;//求出x在位图中第几个位置
			int pos = x % 32; //求出是x是第几位
			return _array[index] & (1 << pos);//判断数据x是否在位图中
		}
		size_t Count()
		{
			return _num;
		}
	private:
		vector<int> _array;
		size_t _num;//保存位图中存储的数据个数
	};

}

         //Test.cpp--测试代码

void TestBitSet()
{
	using namespace qyy;
	BitSet bit(100);

	bit.set(1);
	bit.set(4);
	bit.set(9);
	bit.set(90);
	bit.reset(90);
	for (int i = 0; i < 100; ++i)
	{
		printf("[%d] : %d\n", i, bit.test(i));
	}
}

       问题: 如何在40亿个不重复的无符号整数中查找某个数是否存在 ?

        解决方案:

        1.遍历查找(时间复杂度O(N))

        2.排序(O(N*logN)),然后利用二分查找

        3.位图解决(由于数据量很大,且不重复所以位图是比较优的一种解决方案) 

                将所有的数据都存到位图中,如果想要查找某个数,只需要去位图中找一次就可以找到了,而且位图存储很节约空间。

        

void BitFind(int & x)
{
	qyy::BitSet st(-1);//开无符号整数的最大数的数量个位
	
		//加载数据并存放到位图中

	//查找某个数据在不在位图中
	st.test(x);
}

        1.3位图的应用 

        1.快速查找某个数是否在一个集合中

        2.排序+去重

        3.求两个集合的交集和并集

        4.操作系统中的磁盘块标记 

2.布隆过滤器

        2.1布隆过滤器的提出

        我们平时在刷抖音的时候,它会不停地给我们推荐新的内容,每次它推荐的时候,都要对内容进行判断避免将已经推荐过的内容再次推荐给我们,那么问题来了,它是如何进行推荐的 ?用服务器记录用户看过的内容,当系统推荐新闻时会从用户的历史记录里面进行筛选,过滤掉那些已经存在的记录,那么如何进行快速查找呢?

        方法:

        1.用哈希表存储用户记录,缺点:浪费空间。

        2.用位图存储用户记录,缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理了。

        3.将位图和哈希表结合,即布隆过滤器。

        2.2布隆过滤器的概念

        布隆过滤器时由布隆在1970年提出的一种紧凑型,比较巧妙的概率型数据结构,特点是高效的插入和查询,可以告诉你“某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图中进行存储。此种方法不仅可以提升查询效率还可以节省大量的空间。

        2.3布隆过滤器的插入        

        向布隆过滤器中插入一个字符串,首先这个字符串通过不同的 字符串哈希函数,可以找到不同的位置,然后将布隆过滤器中的这些位置都设置为1.

	struct HashString1
	{
		//BKDRHash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			for (int i = 0; i < str.size(); ++i)
			{
				hash *= 131;
				hash += str[i];
			}
			return hash;
		}
	};
	struct HashString2
	{
		//SDBM Hash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			for (int i = 0; i < str.size(); ++i)
			{
				hash *= 65599;
				hash += str[i];
			}
			return hash;
		}
	};
	struct HashString3
	{
		//RS Hash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			size_t magic = 63689;
			for (int i = 0; i < str.size(); ++i)
			{
				hash = hash * magic + str[i];
				magic *= 378551;
			}
			return hash;
		}
	};
	void set(const T& key)//将数据加入布隆过滤器
	{
		int index1 = Hash1()(key) % N;//避免超出位图的范围	
		int index2 = Hash2()(key) % N;
		int index3 = Hash3()(key) % N;
		_bs.set(index1);
		_bs.set(index2);
		_bs.set(index3);
	}

        2.4布隆过滤器的查找

         布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射的位置的bit一定是1,所以可以按照一下的方式进行查找:分别计算每个哈希值对应的位图中的存贮位置是否为1 ,如果都为1的话,这个元素可能是存在的,如果有一个为0则说明这个元素一定不存在。

        注意:布隆过滤器说某个元素不存在的时候说明这个元素一定不存在,但是如果布隆过滤器说某个元素存在,则说明这个元素可能存在,因为有些哈希函数存在一定的误判。

        2.5布隆过滤器的删除

        布隆过滤器不能直接删除元素,因为布隆过滤器是将一个元素映射到位图中的不同位置,所以可能关键字不同的元素映射到相同的位置,所以删除一个元素可能会影响到其它的元素。

        一种支持删除的方法是:将布隆过滤器的每个比特位扩展为一个小的计数器,插入元素的时候给K个计算器(每次插入元素时,将对应的计数器加1),删除元素时给K个计算器-1,通过多占几倍存储空间的代价增加删除操作。

        缺陷:

                1.无法确认元素是否真正在布隆过滤器中

                2.存在计数回绕 

        //布隆过滤器的实现代码

         

#include"BitSet.h"
#include<string>
namespace qyy
{
	struct HashString1
	{
		//BKDRHash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			for (int i = 0; i < str.size(); ++i)
			{
				hash *= 131;
				hash += str[i];
			}
			return hash;
		}
	};
	struct HashString2
	{
		//SDBM Hash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			for (int i = 0; i < str.size(); ++i)
			{
				hash *= 65599;
				hash += str[i];
			}
			return hash;
		}
	};
	struct HashString3
	{
		//RS Hash
		size_t operator()(const string& str)
		{
			size_t hash = 0;
			size_t magic = 63689;
			for (int i = 0; i < str.size(); ++i)
			{
				hash = hash * magic + str[i];
				magic *= 378551;
			}
			return hash;
		}
	};
	template<size_t N,size_t X = 5 ,class T = string,class Hash1 = HashString1,class Hash2 = HashString2,class Hash3 = HashString3>
	class BloomFilter//布隆过滤器
	{
	public:
		BloomFilter()
			:_bs(N*X)
		{}
		void set(const T& key)//将数据加入布隆过滤器
		{
			int index1 = Hash1()(key) % N;//避免超出位图的范围
			
			int index2 = Hash2()(key) % N;
			int index3 = Hash3()(key) % N;
			_bs.set(index1);
			_bs.set(index2);
			_bs.set(index3);

		}
		bool test(const T& key)//判断数据在不在布隆过滤器
		{
			int index1 = Hash1()(key) % N;//避免超出位图的范围
			int index2 = Hash2()(key) % N;
			int index3 = Hash3()(key) % N;
			if (_bs.test(index1) == false)
				return false;
			if (_bs.test(index2) == false)
				return false;
			if (_bs.test(index3) == false)
				return false;
			return true;
		}
		//void reset(const T& key);//不支持删除,因为可能影响其它值
	private:
		qyy::BitSet _bs; 
	};
}

3.位图和布隆过滤器的优缺点 

        位图的优点:占用的空间少,在数据量很多的时候很好用,缺点:只能支持整形数据且对存在哈希冲突的数据不好处理。

        布隆过滤器的优点:

        1.增加和查询的时间复杂度为O(K)(K为哈希函数的个数,一般较小)。

        2.哈希函数之间相互,没有关系,方便硬件并行运算。

        3.布隆过滤器不需要存储数据本身对于一些保密要求严格的场所有很大的优势。

        4.在能够承受一定的误判的情况下,布隆过滤器比其他数据结构有很大的空间优势。

        5.数据量很大时,布隆过滤器可以表示全集,其他数据结构不能

        6.使用同一组散列函数的布隆过滤器可以进行交,并,差运算。 

        布隆过滤器的缺点:

        1.存在一定的误判率,即假阳性,即不能准确的判断元素的是否在集合中(补救方法:再建一个白名单存储可能出现误判的数据)

        2.不能获取元素本身。

        3.一般情况下不能再布隆过滤器中删除元素。

        4.如果采取计数方法删除,可能存在计数回绕问题。 

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

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

相关文章

Sui Gaming AMA精彩内容集锦

9月8日&#xff0c;Sui基金会在Twitter Space举办了一场「游戏」主题的AMA&#xff0c;会议由基金会市场团队的Rainier主持&#xff0c;邀请了Coert Voorhees、Anthony Palma和Bill Allred三位嘉宾分享观点。Coert Voorhees是Arden的联合创始人兼首席执行官&#xff0c;其产品为…

微信小程序——使用 Vant 组件实现 Popup 弹出层(各位置弹出详细代码分享)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【视觉SLAM入门】7.3.后端优化 基于KF/EKF和基于BA图优化的后端,推导及举例分析

"时间倾诉我的故事" 1. 理论推导2. 主流解法3. 用EKF估计状态3.1. 基于EKF代表解法的感悟 4. 用BA法估计状态4.1 构建最小二乘问题4.2 求解BA推导4.3 H的稀疏结构4.4 根据H稀疏性求解4.5 鲁棒核函数4.6 编程注意 5.总结 引入&#xff1a; 前端里程计能给出一个短时间…

Rn视图生成图片并保存到相册

该功能依赖两个组件 完整代码 yarn add react-native-view-shot // 视图生成图片 yarn add expo-media-library // 保存图片import { useState, useRef } from react import ViewShot from "react-native-view-shot" import { View, Text, Button, Image, StyleSh…

【程序猿包邮送书:第五期】考研408书籍数学书籍大放送,多本书籍任君挑选

&#x1f339;欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 爱书不爱输的程序猿&#xff1a;送书第五期 &#x1f6a9;&#x1f6a9;&#x1f6a9;点击直达福利前言01 《数据结构与算法分析》书籍介绍作者简介目录 02 《计算机网…

【docker-compose 跨节点部署 kafka-kraft SASL用户加密集群】全网最新!

一、概述 文本主要讲解使用Docker-compose在三个节点上部署Kafka3.5.1(现阶段最新版本)-kraft模式&#xff0c;加密使用了用户名密码加密的SASL_PLAINTEXTPLAIN方式。SSL加密在我的docker-compose.yml文件基础上微调一下就好。所有的配置都通过环境变量注入&#xff0c;仅将加…

超详细springcloud sentinel教程~

基础 介绍 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 基本概念 资源 资源是 Sent…

灰度变换原理//test later

灰度变换原理 图像灰度变换变换原理&#xff1a;通过变换函数T将原图像像素灰度值r映射为灰度值s&#xff1a; 2、灰度反转 2.1原理 灰度反转&#xff1a;将图像亮暗对调&#xff0c;可以增强图像中暗色区域细节 &#xfffd;&#xfffd;(&#xfffd;)&#xfffd;−1−…

无版权素材集合

一、无版权视频素材 1.pixabay 网址: https://pixabay.com/zh/videos/ 特点:没错&#xff0c;还是这个网站&#xff0c;除了图片&#xff0c;还有大量免费正版高清无水印视频素材&#xff0c;无需注册即可直接下载&#xff0c;支文搜索。你可以在任何地方使用 pixabay 的免费…

深度干货:制造进销存国内现状如何?2023年五大制造进销存最新盘点!

制造进销存是什么&#xff1f;制造进销存的发展如何&#xff1f;制造进销存的优势在哪里&#xff1f;制造进销存都能为企业提供什么&#xff1f;本文将带大家深入浅出的聊聊制造进销存&#xff0c;全面剖析制造进销存的前世今生&#xff0c;并且为大家提供2023年十大制造进销存…

WebGL 视图矩阵、模型视图矩阵

目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点&#xff1a; 观察目标点&#xff1a; 上方向&#xff1a; 在WebGL中&#xff0c;观察者的默认状态应该是这样的&#xff1a; 视图矩阵程序&#xff08;LookAtTriangles.js&#xff09; 实际上&…

红巨星粒子插件 Red Giant Trapcode Suite for mac 2024

Red Giant Trapcode Suite是一款用于在After Effects中模拟和建模3D粒子和效果的软件&#xff0c;由Red Giant Software公司开发。 该软件包包含11种不同的工具&#xff0c;可以帮助用户模拟火、水、烟、雪等粒子效果&#xff0c;以及创建有机视觉效果和3D元素。它还支持在AE与…

机器学习(15)---代价函数、损失函数和目标函数详解

文章目录 一、各自定义二、各自详解三、代价函数和损失函数区别四、例题理解 一、各自定义 1. 代价函数&#xff1a;代价函数&#xff08;Cost Function&#xff09;是定义在整个训练集上的&#xff0c;是所有样本误差的平均&#xff0c;也就是损失函数的平均。它用于衡量模型在…

langchain主要模块(五):Agent以及Wandb

langchain2之Agent以及Wandb langchain1.概念2.主要模块模型输入/输出 (Model I/O)数据连接 (Data connection)链式组装 (Chains)代理 (Agents)内存 (Memory)回调 (Callbacks) 3.AgentAction Agent&#xff1a;Plan-and-Execute-Agent&#xff1a;搜索工具 4.wandb1.注册2.安装…

第七版教材下的PMP考试有多难?

难度没有上升多少的&#xff0c;毕竟新考纲已经考过几轮考试了&#xff0c;如果报了培训班&#xff0c;那是没多大难度&#xff0c;如果自学&#xff0c;也只是难在理解第七版教材&#xff0c;会比第六版难以理解很多&#xff0c;而且第六版的知识也仍然有用&#xff0c;只是相…

Python基础学习笔记1(AI Studio)

地址&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训社区 课程地址&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训社区 课程地址&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训社区 课程地址&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训…

FE_Vue学习笔记 - 数据代理

Vue中的数据代理是一种机制&#xff0c;通过它&#xff0c;Vue实例&#xff08;vm&#xff09;可以代理其数据对象&#xff08;data&#xff09;中的属性操作。这种代理的原理主要是通过Object.defineProperty()方法&#xff0c;将data对象的每个属性都添加到vm对象上&#xff…

2023年8月京东洗衣机行业品牌销售排行榜(京东数据挖掘)

鲸参谋监测的京东平台8月份洗衣机市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;8月份&#xff0c;京东平台上洗衣机的销量共计117万&#xff0c;环比增长约5%&#xff0c;同比下降约8%&#xff1b;销售额为18亿&#xff0c;环比下降约2%&#xff0c;同…

使用SimpleDateFormat类的示例文档

以下是Java中使用SimpleDateFormat类的示例文档&#xff1a; 示例 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class Main {public static void main(String[] args) {String dateStr…

遥感数据与作物模型同化应用:PROSAIL模型、DSSAT模型、参数敏感性分析、数据同化算法、模型耦合、精度验证等主要环节

查看原文>>>遥感数据与作物模型同化实践技术应用 基于过程的作物生长模拟模型DSSAT是现代农业系统研究的有力工具&#xff0c;可以定量描述作物生长发育和产量形成过程及其与气候因子、土壤环境、品种类型和技术措施之间的关系&#xff0c;为不同条件下作物生长发育及…