布隆过滤器

news2024/11/19 9:30:11

文章目录

  • 前导
  • 布隆过滤器
    • 特点
    • 映射方式
    • hash 函数
    • BloomFilter
      • set
      • test
      • reset
      • 相关问题
    • 应用
      • 示例
        • 哈希切分
          • 例子

今天是1024程序员节,祝各位节日快乐啦!!!

前导

我们之前使用位图bitset,只能将一个整数映射到比特位上,来判断某个数是否存在

但是假如我们也想把判断一个字符串是否存在呢?
我们如何一个字符串映射到一个位置上,应该这么操作呢?
所以就出现了今天要介绍的布隆过滤器

布隆过滤器

特点

  • 对于不存在的值,查找一定是不存在
  • 对于存在的值,查找可能会不准确

映射方式

我们之前学过hash,字符串映射可以有字符串映射的hash函数,把对应的字符串映射到某个位置上,但是如果我们也使用那样的方式会出现什么问题呢?

  1. 对于不存在的字符串,我们使用hash检测,没有问题
  2. 但是对于存在的自负床,那么就有可能会出现hash冲突的,可能会出现误判,

这里我们无法解决冲突的问题,那么我们就要尽可能的降低冲突

所以我们就要对一个字符串使用多个hash函数映射 ,映射到不同的地方,来降低冲突

在这里插入图片描述

hash 函数

这里我们运用3个hash函数,来索引到不同的位置

BKDRHash

struct BKDRHash //特化,全特化,这个是最强的
{
    size_t operator()(const string &key)
    {
        size_t ret = 0;
        for (auto e : key)
        {
            ret *= 31;
            ret += e;
        }
        return ret;
    }
};

APHashs

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

DJBHash

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

BloomFilter

template <size_t N, class K = string, class HashFunc1 = BKDRHash, class HashFunc2 = APHash, class HashFunc3 = DJBHash> //给个默认类型,一个值我们让他映射3个位置
class BloomFilter
{
private:
    bitset<N * 4> _bs; //给个模板参数,要开多少bit位
public:
    void set(const K &key);
    bool test(const K &key);

set

把一个字符串设置进bloomfilter里面
因为我们使用了3个函数函数映射了3个位置,同时还要和开辟的bit位进行取模,映射到对应的位置


    void set(const K &key)
    {
        //标记成存在
        HashFunc1 h1;
        HashFunc2 h2;
        HashFunc3 h3;

        size_t len = 4 * N;
        size_t index1 = h1(key) % len;
        size_t index2 = h2(key) % len;
        size_t index3 = h3(key) % len;

        _bs.set(index1);
        _bs.set(index2);
        _bs.set(index3);
    }

test

因为我们映射到了3个不同的位置,所以如果一个索引位不在,就不在,但是如果3个索引位都在,它大概率就在,但也会出现误判

    bool test(const K &key)
    {
        //因为我们映射到了3个位置,所以一个在不能说明它就在,但是如果一个不在,他就不在
        HashFunc1 h1;
        HashFunc2 h2;
        HashFunc3 h3;

        size_t len = 4 * N;
        size_t index1 = h1(key) % len;
        size_t index2 = h2(key) % len;
        size_t index3 = h3(key) % len;
        // cout << index1 << endl;
        // cout << index2 << endl;
        // cout << index3 << endl;
        if (_bs.test(index1) == false)
            return false;
        if (_bs.test(index2) == false)
            return false;
        if (_bs.test(index3) == false)
            return false;

        //前面只要有一个位不在,就是不在
        //走到这里,就是三个位都存在,但是也可能会出现误判
        return true;
    }

reset

我们需要删除吗?

其实对于bloom过滤器来说,我们不需要删除

原因

  • 把对应的位删除,删除自己的同时可能会把和别人冲突的位也删掉了,会影响到别的值

那么如何扩展一下,使得布隆过滤器能够支持删除

  • 每个位置存储多个bit位,存储引用计数,(有多少个值映射到了当前的位置)
    缺点
  • 使用引用计数可以支持删除,但是整体消耗空间变多了,达不到我们的目的,所以我们还是尽量不支持删除

相关问题

  • 如何选择哈希函数,布隆过滤器的长度
  1. 一个数映射到多个位置,我们给的布隆过滤器长度偏小,很容易映射满,出错率高,所以布隆过滤器长度大,出错率低
  2. 哈希函数越多,映射位置越多,准确性高,但是效率低,所以哈希函数个数和效率成反比,和准确率成正比

在这里插入图片描述* 公式
在这里插入图片描述k 为哈希函数个数,m 为布隆过滤器长度,n 为插入的元素个数,p 为误报率

应用

使用场景

数据量大节省空间允许误判,这样的场景,就可以使用布隆过滤器

  1. 用户注册

    用户进行注册页面时候输入昵称密码
    按正常逻辑,我们就要在数据库里面对昵称判断是否存在,获得结果返回,但是在数据库操作太慢了,还有网络时延
    那么我们就可以使用bloomfilter,把所有的数据,加载到里面
    如果不存在,这是准确的,就可以直接进行操作
    如果存在,就继续到数据库里面进行判断

  2. 垃圾邮件

如果是垃圾邮件,就可以把它放到一个垃圾邮箱里面,就标记一个黑名单,放到布隆过滤器里面,
以后接收邮件,就判断该人是否在黑名单里面,在就不收,否则就收

总结:利用布隆过滤器可以减少和磁盘的IO,或者网络请求,因为访问本地的数据库速度很慢,更不要说跨网络数据传递
这样我们就可以使用布隆过滤器,先进行赛选,不在的话,就没有后续的操作,在的话再去准确的查询

示例

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

近似:把这分别的两份100亿的query查询都放进布隆过滤器,两个地方都存在就是交集,都不存在就不是交集,这个时候是近似的交集(但是会存在不是交集的进去)

但是如果想要使用准确的算法,我们就需要使用哈希切分

哈希切分

哈希切分就可以实现精确查询
A           B
假设A有100G,那么切成多份,但是我们需要使用哈希切,而不是平均切
读取query,使用hash算法,如i=BKDRhash(query)%200;我们要创建是200个小文件
这个query就进入ai好的小文件

同样B也是一样的

这样相同的就进入同一个小文件
Ai和Bi小文件找交集即可:因为相同的query一定进入了编号相同的小文件
这样就加载到内存,放进set相同就有,不同就没

有可能有的桶很大,有的桶很小,找交集不好找
如果Ai和Bi都太大,超过内存,可以考虑换个哈希算法,再切分一次,
例子
<u>一个超过100G的log file log中存这IP地址,涉及算法找到出现次数最多的IP(统计次数),如何找到TOPK的IP,如何直接使用Linux系统命令</u>

 一次读取ip,i=BKDRHash(ip)%200;//分成100份
 i是多少,ip就进入对应的编号的i小文件里面
 相同的ip一定进入了同一个小文件,那么我们使用map统计一个小文件中的ip的次数,就是它准确的次数
 pair<string,int> maxCountIP

 出现次数最多的10个ip
 priority_queue<pair<string,int>,vector<pair<string,int>>,greater> minhead;小堆

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

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

相关文章

【Linux】yum 与 vim 的基本使用

文章目录一、yum 背景知识1、商业生态2、开源生态3、软件生态本土化二、yum 的基本使用1、查看软件包2、安装软件3、卸载软件三、vim 的基本使用1、vim 的基本概念2、vim 的基本操作2.1 模式间切换2.2 光标定位2.3 文本复制2.4 文本编辑2.5 底行模式的操作四、简单 vim 配置2、…

前端工程化<npm、cnpm、yarn、npx、pnpm等包管理工具>

平时工作中&#xff0c;像npm、cnpm、yarn等一些工具都是经常经常用的&#xff0c;但可能对里面的一些细节都没太在意&#xff0c;所以这篇就来总结一下加深印象和理解。另外还有pnpm的使用&#xff0c;以及它的优势 1. npm包管理工具 包管理工具npm Node Package Manager&a…

『Halcon与C#混合编程』011_工业相机的SDK介绍

这里以淘宝上的显微精工店铺的相机为例(支持SDK) 一、相机的SDK简单介绍 第一步:安装好驱动,并能正常打开相机 第二部:找到相机的安装目录,查看厂家提供的Demo和开发手册 在Demo中找到C#的Demo,运行Demo.sln 第三步

基于Matlab使用粒子滤波器和高斯滤波器跟踪单个对象(附源码)

此示例说明了如何使用粒子滤波器和高斯和滤波器来跟踪使用仅范围测量的单个对象。 一、介绍 只能观察范围信息的传感器无法通过单次检测提供对物体状态的完整了解。此外&#xff0c;当以笛卡尔坐标系表示时&#xff0c;仅范围测量的不确定性是非高斯的&#xff0c;并产生凹形…

python作业8

目录 1.输入一个整数判断奇数偶数 2.判断一个数是否能被7或11整除但不能同时整除 3.判断某一年是否为闰年&#xff1a;能被4整除但不能被100整除&#xff0c;或者能被400整除 4.《车辆驾驶人员血液、呼气酒精含量阈值与检验》标准中规定&#xff1a;驾驶员血液酒精小于20mg/…

基于Hi3861的听话的狗子

听话的狗子一、项目介绍二、硬件介绍&#xff08;1&#xff09;Hi3861最小系统电路&#xff08;2&#xff09;电源管理电路&#xff08;3&#xff09;USB转串口电路烧录电路&#xff08;4&#xff09;外设接口电路三、PCB设计四、软件部分简介&#xff08;1&#xff09;代码整体…

在 ESP 开发板上开发 UI 不再复杂

如果您尝试过在没有图形库的情况下开发 UI&#xff0c;那么您一定知道这有多困难。幸运的是&#xff0c;由乐鑫芯片驱动的屏幕&#xff0c;可支持用户使用多种图形库来开发 UI&#xff0c; LVGL 就是其中之一。通常情况下&#xff0c;在使用 LVGL 或类似的图形库前&#xff0c;…

SPI、RS232、485、IIC通信协议详细总结

通信协议大全 文章目录通信协议大全前言一、异步通信和同步通信二、RS232和RS4851.RS2322.RS4853.RS232和RS485的区别4.RS232、485与普通串口的区别&#xff1f;三、SPI协议四、IIC协议1.IIC的时序介绍2.IIC传输数据的格式总结前言 通信协议是每一个嵌入式工程师必备的技能。下…

几道简单的Linux驱动相关面试题,你看你会几题?

一、Linux基础 1、任意3种网络操作的Linux命令,并说明他们的含义 1. ifconfig 命令 ifconfig 用于查看和配置 Linux 系统的网络接口。 查看所有网络接口及其状态&#xff1a;ifconfig -a 。 使用 up 和 down 命令启动或停止某个接口&#xff1a;ifconfig eth0 up 和 ifconfi…

WEB渗透扫描与加固

WEB渗透扫描与加固 1.通过PC2中渗透测试平台BackTrack5中的httprint工具对服务器场景Server2003检测HTTP服务器(调用signatures.txt), 并将该操作显示结果“Banner Reported:”之后的字符串作为FLAG提交; 切换路径至/pentest/enumeration/web/httprint下 使用命令./httpr…

阿里巴巴面试题- - -多线程并发篇(二十九)

前言:七月末八月初的时候,秋招正式打响,公司会放出大量的全职和实习岗位。为了帮助秋招的小伙伴们,学长这里整理了一系列的秋招面试题给大家,所以小伙伴们不用太过焦虑,相信你们一定能超常发挥,收到心仪公司的Offer~~ 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elast…

网络安全:技术趋势

下面列出了GlobalData确定的影响网络安全的关键技术趋势。 维护IT系统的安全性是各种类型组织的一项长期任务。网络攻击频繁且越来越复杂&#xff0c;由那些推动地缘政治事业的人或意图赚钱的攻击者实施。2021年&#xff0c;由于员工在疫情期间远程工作&#xff0c;企业在网络…

直流信号隔离采样

前言 最近在做一个案子&#xff0c;这个案子中的一点是高压电压信号隔离采样&#xff1b; 常见的隔离有&#xff1a; 光隔离&#xff08;光耦&#xff09; 磁隔离&#xff08;霍尔&#xff0c;变压器&#xff09; 等等。 那么要测量直流电压线性隔离如何实现&#xff1f;…

C语言中程序的环境和预处理简述

文章目录程序是如何执行的?翻译预编译条件编译文件的包含嵌套引用不同的引用方式预定义符号编译汇编链接运行程序是如何执行的? 有时候会问自己&#xff0c;程序的运行是那么简单的事情吗&#xff1f; 我鼠标点到 visual studio 上,程序就跑起来了&#xff0c;然后在界面就能…

项目管理:如何使用甘特图制定项目计划

甘特图能够很直观地显示项目任务、进度随着时间推进的进展情况。 横轴为时间&#xff0c;纵轴为项目事项&#xff0c;用条形图的方式直观地展现项目中所有任务的时间及进度。 它可以直观地表明项目中有哪些任务&#xff1f;任务计划在什么时候进行&#xff0c;及实际进展与计划…

基于Vue+node的图书馆座位预约选座管理系统

目 录 一、绪论 1 &#xff08;一&#xff09;选题背景简介 1 &#xff08;二&#xff09;目的和意义 2 &#xff08;三&#xff09;基本内容及目标 2 二 技术简介 4 &#xff08;一&#xff09; React 4 &#xff08;二&#xff09;Vue 4 &#xff08;三&#xff09;Egg.js 5 …

生产者消费者模型

什么是生产者消费者模型&#xff1f; 生产者和消费是操作系统中一种重要的模型&#xff0c;它描述的是一种等待和通知的机制。一、概念引入 日常生活中&#xff0c;每当我们缺少某些生活用品时&#xff0c;我们都会去超市进行购买&#xff0c;那么&#xff0c;你有没有想过&am…

Node.js之Hello World

目录 简介 1.安装 2.安装后的效果 3.准备尝试运行的代码 4.运行JS代码 5.访问正在运行的代码(Hello World) 简介 Node.js 是一个基于"Chrome V8 引擎" 的JavaScript "运行环境"&#xff1b; NodeJS不是一门编程语言, NodeJS是一个运行环境&#xff…

C语言题解 | 消失的数字轮转数组

… &#x1f333;&#x1f332;&#x1f331;本文已收录至&#xff1a;C语言题解系列 更多知识尽在此专栏中&#xff01; &#x1f389;&#x1f389;&#x1f389;欢迎点赞、收藏、关注 &#x1f389;&#x1f389;&#x1f389;文章目录&#x1f349;前言&#x1f349;正文&…

这才是使用ps命令的正确姿势

这才是使用ps命令的正确姿势 前言 在linux系统当中我们通常会使用命令去查看一些系统的进程信息&#xff0c;我们最常使用的就是 ps (process status)。ps 命令主要是用于查看当前正在运行的程序&#xff0c;以及他们相关的的信息&#xff0c;我们可以通过不同的选项进行查看…