当前位置: 首页 > news >正文

【C++哈希应用】位图、布隆过滤器

【C++哈希应用】位图、布隆过滤器

目录

  • 【C++哈希应用】位图、布隆过滤器
      • 位图概念
      • 位图的实现
      • 位图改造
      • 位图应用总结
      • 布隆过滤器
        • 布隆过滤器的提出
        • 布隆过滤器的概念
        • 布隆过滤器的查找
        • 布隆过滤器删除
        • 布隆过滤器优点
        • 布隆过滤器缺陷

作者:爱写代码的刚子

时间:2023.9.30

前言:本篇博客介绍hash应用部分——位图和布隆过滤器,利用位图和布隆过滤器解决一些特定场景的问题。

位图概念

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

数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比 特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:

在这里插入图片描述

位图的实现

template<size_t N>class bitset{public:bitset(){_a.resize(N/32+1);//不要忘了+1,默认初始化成0}void set( size_t x){int i=x/32;int j=x%32;_a[i] |=(1<<j);}void reset(size_t x){int i=x/32;int j=x%32;_a[i] &= (~(1<<j));}bool test(size_t x){int i=x/32;int j=x%32;return _a[i] &(1<<j);}private:vector<int> _a; };

位图改造

用两个位图来测试数据个数

template<size_t N>class twobitset{public:void set(size_t x){//00->01if(!_b1.test(x)&&!_b2.test(x)){_b2.set(x);}//01->10else if(!_b1.test(x)&&_b2.test(x)){_b1.set(x);_b2.reset(x);}}bool is_once(size_t x){return !_b1.test(x)&&_b2.test(x);}bool is_or_above_twice(size_t x){return _b1.test(x)&&!_b2.test(x);}private:bitset<N> _b1;bitset<N> _b2;};

位图应用总结

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

布隆过滤器

布隆过滤器的提出

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

  1. 用哈希表存储用户记录,缺点:浪费空间
  2. 用位图存储用户记录,缺点:不能处理哈希冲突 3. 将哈希与位图结合,即布隆过滤器
布隆过滤器的概念

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

在这里插入图片描述

// 假设布隆过滤器中元素类型为K,每个元素对应5个哈希函数
template<class K, class KToInt1 = KeyToInt1, class KToInt2 = KeyToInt2,class KToInt3 = KeyToInt3, class KToInt4 = KeyToInt4,class KToInt5 = KeyToInt5>
class BloomFilter
{
public:BloomFilter(size_t size) // 布隆过滤器中元素个数 : _bmp(5*size), _size(0){}bool Insert(const K& key){size_t bitCount = _bmp.Size();size_t index1 = KToInt1()(key)%bitCount;size_t index2 = KToInt2()(key)%bitCount;size_t index3 = KToInt3()(key)%bitCount;size_t index4 = KToInt4()(key)%bitCount;size_t index5 = KToInt5()(key)%bitCount;_bmp.Set(index1); _bmp.Set(index2);_bmp.Set(index3);_bmp.Set(index4);_bmp.Set(index5);_size++;} 
private:bitset _bmp;size_t _size;// 实际元素的个数
}
布隆过滤器的查找

布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1。 所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零, 代表该元素一定不在哈希表中,否则可能在哈希表中

bool IsInBloomFilter(const K& key)
{size_t bitCount = _bmp.Size();size_t index1 = KToInt1()(key)%bitCount;if(!_bmp.Test(index1))return false;size_t index2 = KToInt2()(key)%bitCount;if(!_bmp.Test(index2))return false;size_t index3 = KToInt3()(key)%bitCount;if(!_bmp.Test(index3))return false;size_t index4 = KToInt4()(key)%bitCount;if(!_bmp.Test(index4))return false;size_t index5 = KToInt5()(key)%bitCount;if(!_bmp.Test(index5))
return false; return true; // 有可能在
}

注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因为有些哈希函数存在一定的误判。比如:在布隆过滤器中查找"alibaba"时,假设3个哈希函数计算的哈希值为:1、3、7,刚好和其他元素的比特位重叠,此时布隆过滤器告诉该元素存在,但实该元素是不存在的。

布隆过滤器删除

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。

比如:删除上图中"tencent"元素,如果直接将该元素所对应的二进制比特位置0,“baidu”元素也被删除了, 因为这两个元素在多个哈希函数计算出的比特位上刚好有重叠。

一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。

缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕
布隆过滤器优点
  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关

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

  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势

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

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

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

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

附:

一致性哈希

哈希与加密

相关文章:

【C++哈希应用】位图、布隆过滤器

【C哈希应用】位图、布隆过滤器 目录 【C哈希应用】位图、布隆过滤器位图概念位图的实现位图改造位图应用总结布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的查找布隆过滤器删除布隆过滤器优点布隆过滤器缺陷 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9…...

Qt 编译纯c的C99的项目, error: undefined reference to `f()‘

把Cpp的后缀该为C是什么样的 尝试引用一个奇门排盘的c程序&#xff0c;在git上找到的叫cqm&#xff0c; 然后总是报错 error: undefined reference to f() 很是郁闷 于是新建了个项目试验一下&#xff0c;终于摸清了需要命名空间。 后来这么写就可以了 a.h namespace XX …...

TensorFlow入门(五、指定GPU运算)

一般情况下,下载的TensorFlow版本如果是GPU版本,在运行过程中TensorFlow能自动检测。如果检测到GPU,TensorFlow会默认利用找到的第一个GPU来执行操作。如果机器上有超过一个可用的GPU,除第一个之外的其他GPU默认是不参与计算的。如果想让TensorFlow使用这些GPU执行操作,需要将运…...

Unity - 实践: Metallic流程贴图 转 Specular流程贴图

文章目录 目的Metallic Flow - SP - 输出输出的 MRA (MGA) 贴图 Metallic->Specular (根据教程一步一步实践)1. Base color Metallic -> Diffuse2. Base color Metallic -> Specular3. Roughness -> Glossiness输出贴图&#xff0c;在 unity 中展示&#xff1a;M…...

第三章:最新版零基础学习 PYTHON 教程(第四节 - Python 运算符—Python 逻辑运算符及示例)

运算符用于对值和变量执行操作。这些是执行算术和逻辑计算的特殊符号。运算符运算的值称为操作数。 表中的内容逻辑运算符 逻辑与运算符 逻辑或运算符 逻辑非运算符 逻辑运算符的求值顺序 逻辑运算符 在 Python 中,逻辑运算符用于条件语句(True 或 False)。它们执行逻辑 AN…...

如何做好测试?(三)功能测试 (Functional Testing, FT)

1. 功能测试的详细介绍&#xff1a; 功能测试 (Functional Testing, FT)&#xff0c;是一种软件测试方法&#xff0c;旨在验证系统的功能是否按照需求规格说明书或用户期望的方式正常工作。它关注系统的整体行为&#xff0c;以确保各个功能模块和组件之间的交互和集成正确。 …...

Ubuntu-Server-22.04安装桌面+VNC

前提&#xff1a;Ubuntu Server安装好后&#xff0c;ubantu其他版本是否适用这里未知&#xff0c;欢迎大佬们前来评论 一、默认没有图形界面&#xff0c;有时觉得用图形界面操作更简单直接&#xff0c;于是用如下命令安装&#xff1a; 1.更新本地环境 sudo apt-get update s…...

职业规划,什么是职业兴趣 - 我喜欢做什么?

能够在工作岗位上面做出成绩的人&#xff0c;都是结合自身兴趣&#xff0c;对职业进行合理规划的那一类。尤其是步入中年以后&#xff0c;能够创造出巨大价值的人&#xff0c;无一例外都是喜欢自己职业的人。没有将兴趣融入工作的人&#xff0c;只能够忍受默默无闻地活着&#…...

基于Java的高校学生党员发展流程管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...

【NLP的python库(03/4) 】: 全面概述

一、说明 Python 对自然语言处理库有丰富的支持。从文本处理、标记化文本并确定其引理开始&#xff0c;到句法分析、解析文本并分配句法角色&#xff0c;再到语义处理&#xff0c;例如识别命名实体、情感分析和文档分类&#xff0c;一切都由至少一个库提供。那么&#xff0c;你…...

面试理论篇三

关于异常机制篇 异常描述 目录 关于异常机制篇异常描述 注&#xff1a;自用 1&#xff0c;Java中的异常分为哪几类&#xff1f;各自的特点是什么&#xff1f; Java中的异常 可以分为 可查异常(Checked Exception)、运行时异常(Runtime Exception) 和 错误(Error)三类。可查异…...

ShardingSphere|shardingJDBC - 在使用数据分片功能情况下无法配置读写分离

问题场景&#xff1a; 最近在学习ShardingSphere&#xff0c;跟着教程一步步做shardingJDBC&#xff0c;但是想在开启数据分片的时候还能使用读写分离&#xff0c;一直失败&#xff0c;开始是一直能读写分离&#xff0c;但是分偏见规则感觉不生效&#xff0c;一直好像是走不进去…...

char s1[len + 1]; 报错说需要常量?

在C中&#xff0c;字符数组的大小必须是常量表达式&#xff0c;不能使用变量 len 作为数组大小。为了解决这个问题&#xff0c;你可以使用 new 运算符动态分配字符数组的内存&#xff0c;但在使用完后需要手动释放。 还有啥是只能这样的&#xff0c;还是说所有的动态都需要new&…...

【Linux】CentOS-6.8超详细安装教程

文章目录 1.CentOS介绍&#xff1a;2.必要准备&#xff1a;3.创建虚拟机&#xff1a;4 .安装系统 1.CentOS介绍&#xff1a; CentOS是一种基于开放源代码的Linux操作系统&#xff0c;它以其稳定性、安全性和可靠性而闻名&#xff0c;它有以下特点&#xff1a; 开源性&#xff1…...

【Java 进阶篇】MySQL启动与关闭、目录结构以及 SQL 相关概念

MySQL 服务启动与关闭 MySQL是一个常用的关系型数据库管理系统&#xff0c;通过启动和关闭MySQL服务&#xff0c;可以控制数据库的运行状态。本节将介绍如何在Windows和Linux系统上启动和关闭MySQL服务。 在Windows上启动和关闭MySQL服务 启动MySQL服务 在Windows上&#x…...

Android 11.0 mt6771新增分区功能实现一

1.前言 在11.0的系统开发中,在对某些特殊模块中关于数据的存储方面等需要新增分区来保存, 所以就需要在系统分区新增分区,接下来就来实现这个功能 2.mt6771新增分区功能实现一的核心类 build/make/core/Makefile build/make/core/board_config.mk build/make/core/config…...

LiveData简单使用

1.LiveData是基于观察者模式&#xff0c;可以用于处理消息的订阅分发的组件。 LiveData组件有以下特性&#xff1a; 1) 可以感知Activity、Fragment生命周期变化&#xff0c;因为他把自己注册成LifecycleObserver。 2) LiveData可以注册多个观察者&#xff0c;只有数据…...

手动实现Transformer

Transformer和BERT可谓是LLM的基础模型&#xff0c;彻底搞懂极其必要。Transformer最初设想是作为文本翻译模型使用的&#xff0c;而BERT模型构建使用了Transformer的部分组件&#xff0c;如果理解了Transformer&#xff0c;则能很轻松地理解BERT。 一.Transformer模型架构 1…...

leetcode456 132 Pattern

给定数组&#xff0c;找到 i < j < k i < j < k i<j<k&#xff0c;使得 n u m s [ i ] < n u m s [ k ] < n u m s [ j ] nums[i] < nums[k] < nums[j] nums[i]<nums[k]<nums[j] 最开始肯定想着三重循环&#xff0c;时间复杂度 O ( n 3 )…...

WordPress外贸建站Astra免费版教程指南(2023)

在WordPress的外贸建站主题中&#xff0c;有许多备受欢迎的主题&#xff0c;如AAvada、Astra、Hello、Kadence等最佳WordPress外贸主题&#xff0c;它们都能满足建站需求并在市场上广受认可。然而&#xff0c;今天我要介绍的是一个不断颠覆建站人员思维的黑马——Astra主题。 …...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...