C++进阶篇5---番外-位图和布隆过滤器

哈希的应用

一、位图

情景:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中???

看到查找元素的范围,暴力肯定是过不了的,我们要么二分要么哈希,但是二分要求排序,题目说没排过序,只剩下哈希,但是如果用正常的哈希表肯定不行,数据量太大了(可以算一下,大概15G),根本加载不进内存,更别谈放到哈希表中了,那怎么办? 

这时候就需要用到位图---本质就是状态压缩版的哈希表,用一个比特位表示一个数字,大大压缩了数据量,(整形是4字节,如果是哈希表只能用来表示一个数字,但是位图可以用来表示4*8=32个数),数据量缩小了32倍,大概0.5G,具体的实现如下

namespace zxws
{template <size_t N=100>class bitset{public:bitset(){bit.resize(N/32+1);}void set(size_t x)//增{size_t i = x / 32;size_t j = x % 32;bit[i] |= (1u << j);//1u代表unsigned int类型的1}void reset(size_t x)//删{size_t i = x / 32;size_t j = x % 32;bit[i] &= ~(1u << j);}bool test(size_t x)//查{size_t i = x / 32;size_t j = x % 32;return (bit[i] >> j) & 1u;}private:vector<int>bit;};
}

模拟实现没啥难度,就是要了解位运算,当然这只是位图的最重要的几个函数,还有一些其他的不常用的就不模拟实现了,有兴趣大家可以去查看文档

那么了解了位图的实现原理,我们再来看看下面的几个题

1. 给定100亿个整数,设计算法找到只出现一次的整数?
2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
题1:正常用一个位图,不好做,因为一个数字对应一个比特位,而一个比特位只有0 / 1两个状态,无法表示没出现,出现1次和出现多次这3个状态,那怎么办?既然一个比特位无法表示,那两个比特位呢?共有00,01,10,11四个状态,绰绰有余,实现如下
namespace zxws
{template <size_t N = 100>class twobitset{public:void set(size_t x){size_t i = x / 32;size_t j = x % 32;if (bs1.test(x) == false && bs2.test(x) == false)//00->01{bs1.set(x);}else if (bs1.test(x) == true && bs2.test(x) == false)//01->10{bs1.reset(x);bs2.set(x);}}void test(size_t x){return bs1.test(x) == true && bs2.test(x) == false;//01--代表只出现一次}private:bitset<N>bs1;bitset<N>bs2;};
}

题2:找文件交集,这个就很明显了,两个位图分别存放两个文件中的数字,然后比特位之间&一下,比特位上为1的就是交集

题3:这题其实和第1题一样,都是查看数字出现次数,要求不出现两次,即有没出现,出现1次,出现2次和出现2次以上四个状态,两个位图正好够了,实现同题1

二、布隆过滤器

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

实现原理图

一般来说用三个哈希函数就差不多了

上图是网上的研究数据显示结果,仅供参考(k,m,n满足上诉关系时,不容易发生哈希冲突)

布隆过滤器的作用范围还是很广泛的,尤其是在不怎么关心某一个东西是否真的存在的场景下,举个例子,比如说取用户ID,当你取的id没人用时,OK你创建成功,当你取的id显示有人用时,如果是真的有人用了,那我们就换一个,如果没人用,它误判了,那我们也就是不能用这个id而已,没有啥太大影响,这时布隆过滤器就非常合适

当然如果说用户投诉说明明没人用这个id,却不让用,要求我们修复bug,这时我们只要让在布隆过滤器过滤后显示为存在的数据再去数据库中校验一下即可,

当然也有人会觉得反正都要去数据库校验还要布隆过滤器干嘛,注意:1.布隆过滤器它为啥叫过滤器,关键就是它只能确定不存在的数据,不能确定存在的数据。2.网络上通讯会比较耗时,如果每一个id的确认都需要与服务器上的数据库校验,就会浪费时间

实现如下

//哈希函数就自行去网上找哪些不容易产生哈希冲突的就行
template <size_t N, class K=string, class HashFunc1=HashFun<K>, class HashFunc2=DGBHash<K>, class HashFunc3=APHash<K> >
class BloomFiler {
public:void set(const K& key){size_t hash1 = HashFunc1()(key) % N;size_t hash2 = HashFunc2()(key) % N;size_t hash3 = HashFunc3()(key) % N;_bs.set(hash1);_bs.set(hash2);_bs.set(hash3);}bool test(const K& key){size_t hash1 = HashFunc1()(key) % N;size_t hash2 = HashFunc2()(key) % N;size_t hash3 = HashFunc3()(key) % N;if (_bs.test(hash1) == false|| _bs.test(hash2) == false|| _bs.test(hash3) == false)return false;return true;}
private:bitset<N*5>_bs;
};

两个问题:

1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法(具体下面一个专题讲)

2. 如何扩展BloomFilter使得它支持删除元素的操作?一般来说是不能支持的,因为删除一个元素的映射会影响其他元素的哈希映射(因为它们会出现冲突),但是我们可以给它们加一个引用计数,这样就能在删除它的同时不影响其他元素的映射

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

三、哈希分割---哈希思想的扩展

给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?如何找到top K的IP?

100G的file很显然太大,我们的想法是将它分割成一个个小文件,然后在小文件中计数,我们将文件按Hash(id) % 100,得到100个1G的小文件(理想情况),然后我们就可以在小文件中统计每个id出现的次数(因为同一个id经过哈希映射会在同一个小文件中),但是,上面的只是理想情况,如果某一个小文件的大小为10G,也就是分完之后还是太大了,我们又该怎么办?

出现上诉情况共分两种可能:

1.相同的id太多
2.哈希冲突太多,导致多个不同的id都放在了同一个小文件中

如果是情况一,我们不用管,map中只会插入一次这个id,空间足够

如果是情况二,会报内存错误,这时我们就对这个小文件进行二次哈希分割即可

top K问题用堆实现就行,之前再二叉树数据结构中讲过的


下面,我们回过头去看看

给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法

近似算法就是用布隆过滤器,但是精确的算法呢?

这个query的大小也要考虑到,假设query的大小为50字节,那么一共5000亿字节,约等于500G,很明显了哈希切割,当然我们得先将query转成整数,Hash(query)%500,两个文件各自分成500个1G的小文件(理想情况),这样两个文件中相同的query会分别放在同一个余数的两个小文件中,如下图

当然它也会出现小文件太大的情况,处理方法同上,注意这个不能用位图的原因是query里面存的不一定是整数,这样不同的query查询也有可能映射到用一个比特位(这也是布隆过滤器不准确的原因之一),就不精确了


如果上诉内容对你理解哈希有帮助的话,不要忘记点赞+评论哟!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows搭建gitlab教程

1.安装gitlab 说明&#xff1a;由于公司都是windows服务器&#xff0c;这里安装以windows为例&#xff0c;先安装一个虚拟机&#xff0c;然后安装一个docker&#xff08;前提条件&#xff09; 1.1搜索镜像 docker search gitlab #搜索所有的docker search gitlab-ce-zh #搜索…

【OpenCV实现图像:使用OpenCV进行物体轮廓排序】

文章目录 概要读取图像获取轮廓轮廓排序小结 概要 在图像处理中&#xff0c;经常需要进行与物体轮廓相关的操作&#xff0c;比如计算目标轮廓的周长、面积等。为了获取目标轮廓的信息&#xff0c;通常使用OpenCV的findContours函数。然而&#xff0c;一旦获得轮廓信息后&#…

Redis跳跃表

前言 跳跃表(skiplist)是一种有序数据结构&#xff0c;它通过在每一个节点中维持多个指向其他节点的指针&#xff0c;从而达到快速访问节点的目的。 跳跃表支持平均O(logN)&#xff0c;最坏O(N)&#xff0c;复杂度的节点查找&#xff0c;还可以通过顺序性来批量处理节点…

城市管理实景三维:打造智慧城市的新引擎

城市管理实景三维&#xff1a;打造智慧城市的新引擎 在城市管理领域&#xff0c;实景三维技术正逐渐成为推动城市发展的新引擎。通过以精准的数字模型呈现城市真实场景&#xff0c;实景三维技术为城市决策提供了全新的思路和工具。从规划设计到交通管理&#xff0c;从环境保护到…

HOOPS Web平台助力开发3D应用,实现超大规模3D web轻量化渲染与数据格式转换!

一、包含的软件开发工具包 HOOPS Web平台帮助开发人员构建基于Web的工程应用程序&#xff0c;提供高级3D Web可视化、准确快速的CAD数据访问和3D数据发布。 HOOPS Web平台包括三个集成软件开发工具包 (SDK)&#xff1a; &#xff08;1&#xff09;Web端3D可视化引擎 HOOPSCom…

五子棋游戏

import pygame #导入pygame模块 pygame.init()#初始化 screen pygame.display.set_mode((750,750))#设置游戏屏幕大小 running True#建立一个事件 while running:#事件运行for event in pygame.event.get():if event.type pygame.QUIT:#当点击事件后退出running False #事…

什么是神经网络(Neural Network,NN)

1 定义 神经网络是一种模拟人类大脑工作方式的计算模型&#xff0c;它是深度学习和机器学习领域的基础。神经网络由大量的节点&#xff08;或称为“神经元”&#xff09;组成&#xff0c;这些节点在网络中相互连接&#xff0c;可以处理复杂的数据输入&#xff0c;执行各种任务…

【蓝桥杯】刷题

刷题网站 记录总结刷题过程中遇到的一些问题 1、最大公约数与最小公倍数 a,bmap(int,input().split())sa*bwhile a%b:a,bb,a%bprint(b,s//b)2.迭代法求平方根(题号1021) #include<stdio.h> #include<math.h> int main() {double x11.0,x2;int a;scanf("%d&…

Self-Supervised Exploration via Disagreement论文笔记

通过分歧进行自我监督探索 0、问题 使用可微的ri直接去更新动作策略的参数的&#xff0c;那是不是就不需要去计算价值函数或者critic网络了&#xff1f; 1、Motivation 高效的探索是RL中长期存在的问题。以前的大多数方式要么陷入具有随机动力学的环境&#xff0c;要么效率…

C++之模版初阶(简单使用模版)

前言 在学习C的模版之前&#xff0c;咱们先来说一说模版的概念&#xff0c;模版在我们的日常生活中非常常见&#xff0c;比如我们要做一个ppt&#xff0c;我们会去在WPS找个ppt的模版&#xff0c;我们只需要写入内容即可&#xff1b;比如我们的数学公式&#xff0c;给公式套值&…

Linux:配置Ubuntu系统的镜像软件下载地址

一、原理介绍 好处&#xff1a;从国内服务器下载APT软件&#xff0c;速度快。 二、配置 我这里配置的是清华大学的镜像服务器地址 https://mirrors.tuna.tsinghua.edu.cn/ 1、备份文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2、清空sources.list ec…

软件测评中心进行安全测试有哪些流程?安全测试报告如何收费?

在当今数字化时代&#xff0c;软件安全测试是每个软件开发团队都不能忽视的重要环节。安全测试是指对软件产品进行系统、全面的安全性评测与检测的过程。它旨在发现并修复软件中存在的漏洞和安全隐患&#xff0c;以确保软件能够在使用过程中保护用户的数据和隐私不被非法访问和…

RabbitMQ 的网页界面操作说明

启动 上面给用户添加了角色和权限&#xff0c; 我们就可以登录了 先手动创建两个队列&#xff0c;然后再把这两个队列和交换机绑定&#xff0c;就可以发布消息 回到队列中看看有什么变化 队列中显示绑定了交换机 再看一下队列中发生的变化 可以看到队列中收到了信息

gitlab

Gitlab 安装git yum安装 [rootgit ~]# yum -y install git编译安装 Git官网 #安装依赖关系 [rootgit ~]# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel autoconf gcc perl-ExtUtils-MakeMaker # 编译安装 [rootgit ~]# tar -zxf git-2.0…

【算法】FFT-1(递归实现)(不包括IFFT)

FFT 多项式多项式乘法复数及运算导数泰勒公式及展开式欧拉公式单位根 FFTCode IFFT 多项式 我们从课本中可以知道&#xff0c;一个 n − 1 n-1 n−1 次的多项式可以写成 a 0 a 1 x a 2 x 2 a 3 x 3 ⋯ a n − 1 x n − 1 a_{0}a_{1}xa_{2}x^2a_{3}x^3\dotsa_{n-1}x^{n-…

智能优化算法应用:基于蝴蝶算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝴蝶算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝴蝶算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝴蝶算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

简易版扫雷+代码分析

前言&#xff1a; 实验一个简易版的扫雷&#xff0c;也要两百来行的代码&#xff0c;因此为了代码整洁&#xff0c;维护起来方便&#xff0c;这里我们和前期实现的三子棋一样&#xff0c;也弄一个游戏的头文件game.h用来装各种头文件以及函数的声明以及宏定义、预处理信息&…

windows的bat文件(学习笔记)

简介 通过windows的cmd执行的批处理&#xff0c;扩展名可以是.bat或.cmd&#xff08;类似linux的shell脚本&#xff09; 所有语句符号不区分大小写 帮助提示信息&#xff1a;命令 /? 1 基本语法 (1) 注释&#xff1a;rem 注释文本不执行 (2) 关闭盘符输出&#xff1a;e…

最新AI创作系统ChatGPT网站运营源码、支持GPT-4-Turbo模型,图片对话识图理解,支持DALL-E3文生图

一、AI创作系统 SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01;本系统使用NestjsVueTypescript框架技术&#xff0c;持续集成AI能力到本系统。支持OpenAI DALL-E3文生图&#xff0c;…

技术面时,一定要掌握这3个关键点

前言 现在有这么多优秀的测试工程师&#xff0c;大家都知道技术面试是不可避免的一个环节&#xff0c;一般技术面试官都会通过自己的方式去考察你的技术功底与基础理论知识。 如果你参加过一些大厂面试&#xff0c;肯定会遇到一些这样的问题&#xff1a; 1、看你项目都用到了…