位图布隆过滤器

位图&&布隆过滤器

  • 位图
    • 位图的实现
    • 位图优缺点
    • 关于位图的题目
    • 位图的应用
  • 布隆过滤器
    • 提出原因
    • 布隆过滤器概念
    • 操作
      • 插入
      • 查找
      • 删除
    • bloom优缺点
    • 关于bloom的题目
    • 实现
  • 哈希切割问题

位图

位图:使用比特位来表示某种状态。比特位为0表示不存在,为1表示存在。
适用于大量的数据且数据没有重复的情况。通常用来判断某个数据存不存在。

位图的实现

namespace xty
{
	// N代表一共有多少个数据	
	template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			//开n/8 + 1个字节,数据初始化为0
			_bits.resize(N / 8 + 1, 0);
		}
		void set(size_t x)
		{
			size_t i = x / 8;        //表示第几个字节
			size_t j = x % 8;        //表示第几个比特位
			_bits[i] |= (1 << j);    //把位置设为1

		}


		void reset(size_t x)
		{
			size_t i = x / 8;//表示第几个字节
			size_t j = x % 8;//表示第几个比特位
			_bits[i] &= (~(1 << j));  //把位置设为0
		}

		bool tset(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			return _bits[i] & (1 << j);
		}

	private:
		vector<char> _bits;
	};



//测试代码
	void bitmaptest()
	{
		bitset<10> bs;
		int a[] = { 1,2, 3,4, 5, 6, 7, 8, 9 };
		for (auto e : a)
		{
			bs.set(e);
		}
		cout << bs.tset(10) << endl;
		int x = 0;
	}

}	

位图优缺点

优点:

  • 速度快,节省空间

缺点:

  • 只能映射整形,其他类型:浮点数、string等等不能存储映射。

关于位图的题目

  1. 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?
    10亿个字节大约是1GB,40亿个整数大约是16GB。把40亿个数全存到内存中是不现实的。
    如果我们使用位图的概念,每个比特位表示一个数,那么只需要40亿个bit(约为512MB)大小的内存即可。大大节省了空间占用。出现的数比特位置为1,不存在的置为0,就可以查找了。

位图的应用

  1. 给定100亿个整数,设计算法,找到只出现一次的整数?
    使用双位图的概念。00表示未出现过,01表示出现过一次,10表示出现过两次。
    实现如下:
	template<size_t N>
	class doubleset
	{
	public:

		void set(size_t x)
		{
			//00->01
			if (_bs1.tset(x) == false
				&& _bs2.tset(x) == false)
			{
				_bs2.set(x);
			}
			// 01->10
			else if (_bs1.tset(x) == false
				&& _bs2.tset(x) == true)
			{
				_bs1.set(x);
				_bs2.reset(x);
			}
		}


		void print()
		{
			for (size_t i = 0; i < N; i++)
			{
				if (_bs2.tset(i))
				{
					cout << i << endl;
				}
			}
		}
	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

	//测试代码
	void double_bit()
	{
		int a[] = { 3, 45, 53, 32, 32, 43, 3, 2, 5, 2, 32, 55, 5, 53,43,9,8,7,8 };
		doubleset<100> bs;
		for (auto e : a)
		{
			bs.set(e);
		}

		bs.print();
	}
  1. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
    解法1:将其中一个文件的值读到内存的一个位图中;再读取另外一个文件,判断在不在上面的位图中,在就是交集!!但是会有重复的值,需要再次去重才可以。
    解法2:
    在这里插入图片描述
    法1适合数据量小的场景,因为判断在不在的时候读的是数据量的个数。
    而法2适合大数据量,不管多少数据只读2^31次方次。并且可以解决多个文件。

  2. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数?
    跟问题1,完全一样,稍微变一下即可。
    在这里插入图片描述

布隆过滤器

参考来源

提出原因

我们在使用新闻客户端看新闻的时候,它会不停的给我们推送新的内容,他每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端系统如何实现推送去重的?用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录进行筛选,过滤掉那些已经存在的记录。如何快速查找呢?

  1. 用哈希表存储用户记录, 缺点:浪费空间
  2. 用位图存储用户记录,缺点:位图一般处理整形,如果内容编号是字符串,就无法处理了。
  3. 将位图与哈希结合,就是布隆过滤器

布隆过滤器概念

布隆过滤器是由布隆(Burton Howard Bloom)提出的概率型数据结构,特点是高效插入和查询,可以用来告诉你:某个东西一定不存在或可能存在,他是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量内存空间。

在这里插入图片描述

操作

插入

将一个关键字使用不同的哈希函数,映射到多个位置,如上图:baidu的插入使用3个哈希函数,映射到三个位置。

查找

bloom判定为不在,是准的。
因为如果不在,三个比特位一定有0。
1有可能是被其他关键字哈希到的,所以说不能判断一定存在。
在这里插入图片描述

删除

bloom不支持删除操作。因为在删除一个元素时,可能会影响到其他元素。
比如:“baidu”和“zijie”都映射到了2这个位置。删了其中一个就要把该比特位置0.这会影响到另一个元素的判断。因此,bloom不支持删除。

一种支持删除的方法:将bloom的每个比特位扩展成一个小计数器,每映射一个,给该比特位加1。删除时,给k个比特位减1。通过多开空间,来实现删除功能。

缺点:

缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕

bloom优缺点

优点:

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

缺点:

  1. 有误判率,即假阳性(补救方法:再建立一个白名单,存储可能会误判的数据)
  2. 不能获取元素本身
  3. 一般情况下,不能从bloom删除元素
  4. 如果采用计数方式删除,可能会存在数据回绕。

关于bloom的题目

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集? 分别给出精确算法和近似算法
    近似算法:第一个文件放入布隆过滤器+第二个文件查询。
    精确算法:使用哈希切分,分别进入每个小文件里面找交集。

在这里插入图片描述
因为不是平均切分,所以可能会出现有些文件过大的情况。如何解决呢?
情况1:单个文件中,有某个大量重复的query
情况2:单个文件中,有大量不同的query
在这里插入图片描述

  1. 如何扩展BloomFilter使得它支持删除元素的操作?
    扩充比特位进行计数。

实现

	template<size_t N, class K,
	class Hash1,
	class Hash2,
	class Hash3>
	class BloomFilter
	{
	public:
		void set(const K& key)
		{
			size_t hash1 = Hash1()(key) % N;   //用到了匿名对象的知识
			_bs.set(hash1);
			size_t hash2 = Hash2()(key) % N;   //用到了匿名对象的知识
			_bs.set(hash2);
			size_t hash3 = Hash3()(key) % N;   //用到了匿名对象的知识
			_bs.set(hash3);
		}


		//在不在
		bool test(const K& key)
		{
			//不在是准的
			size_t hash1 = Hash1()(key) % N;   //用到了匿名对象的知识
			size_t hash2 = Hash2()(key) % N;   //用到了匿名对象的知识
			size_t hash3 = Hash3()(key) % N;   //用到了匿名对象的知识
			if (_bs.test(hash1) == false || _bs.test(hash2) == false
				|| _bs.test(hash3) == false)
			{
				//有一个是假,就说明不在
				return false;
			}


			return true;  //存在误判,
			
		}

	private:
		static const size_t _X = 4;//设置开空间的倍数
		bitset<N* _X> _bs;    //三个哈希函数,开4倍的空间
	};

哈希切割问题

  1. 给一个超过100G大小的log file, log中存着IP地址,设计算法找到出现次数最多的IP地址?与上题条件相同,如何找到top K的IP? 如何直接用Linux系统命令实现?
  • 将文件用哈希切成500个小文件(相同的ip一定进入同一个文件,读取单个文件,就可以统计处ip出现的次数)。
  • 依次处理每个小文件,使用一个unordered_map统计次数。
  • 如果:统计过程中,出现抛内存异常,则说明单个文件过大,冲突太多,需要重新换哈希函数,再次切分这个小文件
  • 如果没有抛异常,则正常统计。统计完一个小文件,记录最大的。clear再统计下一个小文件。

建立K个小根堆,统计。

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

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

相关文章

C语言内存函数:memcpy、memcat、memmove介绍和模拟实现(实用性高,建议三连收藏)

目录 1.memcpy函数 1.1函数介绍 1.2函数示范使用 1.3函数的模拟实现 1.4补充 2.memmove函数 2.1函数介绍 2.2函数的使用示范 2.3函数的模拟实现 3.memcmp(内存比较函数&#xff09; 3.1函数介绍 3.2函数的示范使用&#xff0c;有趣的例子 4.函数补充memset(内存…

Visual Studio 最新版安装教程

Visual Studio简介 Visual Studio是一个集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于.NET和C工作负载以及许多其他语言和框架的开发。它提供了一套完整的工具集&#xff0c;包括UML工具、代码管控工具、集成开发环境&#xff08;IDE&#xff09;等&#xff…

c++重载、隐藏和覆盖

重载 函数名字相同&#xff0c;但参数列表或者返回值不同一组函数要重载必须处在同一作用域中 class Base { public:Base(int data0):m_a(data){}void show(){cout<<"Base::show()"<<endl;}void show(int){cout<<"Base:show(int)"<&l…

Opencv(C++)学习 TBB与OPENMP的加速效果实验与ARM上的实践(二)

在上一篇文章中&#xff0c;我们成功验证了Intel Threading Building Blocks (TBB) 与 OpenMP 在多线程并行处理方面的加速潜力。为了更深入地理解这些技术在实际应用场景中的效能提升&#xff0c;接下来我们将目光转向目标开发板环境&#xff0c;进一步探究这两种框架在嵌入式…

快速排序

思想&#xff1a;分而治之&#xff1b; 确定好基准值然后在两侧递归调用,记好模版就好了 #include<bits/stdc.h> using namespace std; int n; const int N1e610; int q[N]; void quick_sort(int q[],int l,int r) {if(l>r)return ;int xq[l],il-1,jr1;while(i<j…

js数组和字符串之间的转换方式以及数组的一些方法

一、数组和字符串之间的转换方式 1&#xff09;将字符串切割成字符串数组—stringObject.split(separator, howmany) seperator-----字符串、正则表达式&#xff0c;必需 howmany------指定返回的数组的最大长度&#xff0c;可省略&#xff0c;省略后全量返回 源代码 var str&q…

自研人工智能小工具-小蜜蜂(国外ChatGpt的平替)

国内有非常多好用的人工智能工具&#xff0c;但均无法完全替代国外ChatGpt。 ChatGPT相较于其他国内工具的优势在于以下几点&#xff1a; 创新的语言生成能力&#xff1a;ChatGPT是由OpenAI开发的先进的自然语言生成模型&#xff0c;它采用了大规模的预训练和精细调整方法。因此…

揭秘远程控制APP的便捷之美!

在这个科技日新月异的时代&#xff0c;我们的生活被各种手机软件所包围。几乎每个人都有一个甚至多个手机&#xff0c;你是否也有遇到过需要远程操作自己某一台手机的场景呢&#xff1f;今天&#xff0c;我要向大家推荐一款神奇的手机远程操作神器&#xff0c;让你可以随时随地…

格式化日期注解@JsonFormat的使用和TimeZone时区问题

JsonFormat的使用 目的 为了便于date类型字段的序列化和反序列化&#xff0c;需要在数据结构的Date、Timestamp、DateTime类型的字段上用JsonFormat注解进行注解 使用 JsonFormat注解是一个时间格式化注解&#xff0c;比如我们存储在mysql中的数据是date类型的&#xff0c;当…

聊聊比特币----比特币地址

⽐特币地址是⼀个标识符&#xff08;帐号&#xff09;&#xff0c;包含27-34个字母数字拉丁字符&#xff08;0&#xff0c;O&#xff0c;I除外&#xff09;。地址可以以QR码形式表⽰&#xff0c;是匿名的&#xff0c;不包含关于所有者的信息。 地址⽰例&#xff1a;14qViLJfdG…

树状数组复习

基本原理 树状数组的原理简单来说就是利用二进制拆分区间 我们可以对一个数进行二进制分解&#xff0c;最多分解成log(x)个数&#xff0c;同样我们可以对[1,n]这个区间进行分解。也是最多log段&#xff0c;每次修改时我们维护受到影响的区间&#xff0c;然后查询时用这log个区…

ele-h5项目使用vue3+vite开发:第四节、业务组件-SearchView组件开发

需求分析 展示切换动画搜索框输入文字&#xff0c;自动发送请求搜索结果展示搜索状态维护历史搜索展示&#xff0c;点击历史搜索后发送请求历史搜索更多切换动画效果 <script setup lang"ts"> import OpSearch from /components/OpSearch.vue import { ref } f…

前端JavaScript篇之对JSON的理解

目录 对JSON的理解 对JSON的理解 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它以易读易写的文本形式表示结构化数据&#xff0c;比较适合用来在不同的应用程序或平台之间传递数据。 简单来说&#xff0c;JSON就像是一种…

LangChain 81 LangGraph 从入门到精通三

LangChain系列文章 LangChain 60 深入理解LangChain 表达式语言23 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 61 深入理解LangChain 表达式语言24 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 62 深入理解Lang…

Git使用命令大全

命令大全参考阮一峰的博客&#xff0c;根据自己的使用习惯作了调整。 Git常用命令 其他常用的命令 配置Git # 显示当前的Git配置 $ git config --list# 编辑Git配置文件 $ git config -e [--global]# 设置提交代码时的用户信息 $ git config [--global] user.name "[nam…

JAVA工厂方法模式详解

工厂方法模式 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过…

如何结合ChatGPT生成个人魔法咒语词库

3.6.1 ChatGPT辅助力AI绘画 3.6.1.1 给定主题让ChatGPT直接描述 上面给了一个简易主题演示一下&#xff0c;这是完全我没有细化的提问&#xff0c;然后把直接把这些关键词组合在一起。 关键词&#xff1a; 黄山的美景&#xff0c;生机勃勃&#xff0c;湛蓝天空&#xff0c;青…

python使用Netmiko库配置路由器

目录 一&#xff1a;介绍 二&#xff1a;查看路由器接口信息 三&#xff1a;配置ip地址 四&#xff1a;配置防火墙 五&#xff1a;备份配置信息 一&#xff1a;介绍 Netmiko 是一个 Python 库&#xff0c;用于自动化网络设备的交互。它使用 Paramiko 作为其底层库来执行 S…

VSCode 安装LLDB调试器(OS X)并启动调试

插件&#xff1a;&#xff08;LLDB插件安装&#xff09; 安装这个版本不好弄错了&#xff0c;CodeLLDB&#xff08;名字&#xff09; 配置&#xff1a;&#xff08;LLDB启动调试&#xff09; {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更…

[ChatGPT们】ChatGPT 如何辅助编程初探

主页&#xff1a;元存储的博客 全文 9000 字&#xff0c; 原创请勿转载。 我没有写过诗&#xff0c;但有人说我的代码像诗一样优雅 -- 雷军 图片来源&#xff1a;https://www.bilibili.com/video/BV1zL411X7oS/ 1. 引言 作为一个程序员&#xff0c;我们不仅要熟悉各种编程语…