C++布隆过滤器,哈希切割

一、哈希切割(用于处理大量的数据)

        前面我们学过为了实现哈希映射,我们需要一个哈希函数,这里我们也可以使用哈希函数把IP转为整型。比方说我们分成了100份小文件,idx = HashFunc(IP) % 100,idx是几就把它放进几号文件中。

        我们可以把每个小文件理解为一个哈希桶
        这样不一样的IP可能分进同一个小文件中,但是同一个IP一定会分进同一个小文件。

        这里还可能出现一个情况:其中一个小文件的大小可能超过1G(假设超过1G就不够了)。
而超过了1G也有有两种情况:

1️⃣ 不重复的IP很多,map需要很多节点,统计不下。
2️⃣ 重复的IP很多,map不需要很多节点,统计的下。

        针对第一种情况,我们可以换个哈希函数递归切分。
        但是这种方法对情况二无效,因为相同的IP太多,照样会切分超过1G。

所以综合考虑可以这样统计:

不管是啥情况,都直接用map统计,如果是第二种情况就直接统计完成了。
如果是第一种情况,会insert失败,我们可以捕获异常,此时再去换个哈希函数递归切分。

二、布隆过滤器

通过上一篇的讲解我们可以看出:①位图优点是节省空间和效率高
                                                      ②缺点是要求范围相对集中,而且只能是整型。

而如果是字符串我们想使用位图,就可以使用哈希函数转成整型
这里就会有一种情况,不同的字符串可能转换成同一个整型。 会导致误判。

存在是不准确的,如果只有str1和str2,而str3映射的位置跟str2重了,
就会导致原本不在的元素误判成在。
所以布隆过滤器会有两种判断状况
①不存在(百分百准确)
②可能存在(可能误判,即哈希冲突)

2.1、什么是布隆过滤器

        它的主要思想是让一个值映射多个位置。我们可以使用多个哈希函数,多映射几个位置,这里假设有两个哈希函数,映射两个位置。

这样我们要看str2是否存在,必须要同时指向红色和绿色才能判断为存在。

所以布隆过滤器的作用就是降低误判率。映射的位置越多,误判率越低。
但是这里映射的位置也不能太多,映射的多,占的空间也多,找的次数也多,我们使用位图这样的方式就是为了提高效率并且节省空间。映射的多了也就没那么节省空间了。

2.2布隆过滤器的应用场景

【场景一】
        当我们要写一个注册系统的时候,我们注册昵称的时候不能跟别人重复,此时我们就可以采用布隆过滤器,如果不在那么就是准确的,一定不存在。但是如果显示存在,则有可能是误判。因为布隆过滤器中如果存在可能会误判,可以到数据库中再次查询昵称号码存不存在。

有人可能问这有必要加一个布隆过滤器吗?

假设现在来了100不存在的值,大部分都会显示不存在,
只有很小一部分会误判为存在,这样没有误判的大部分效率大大提高。

【场景二】
        我们在访问网站的时候有时候会出现风险网站。我们可以把这些网页加入黑名单,在我们访问网站之前就先经过布隆过滤器,有风险就可以快速的判断。

2.3 布隆过滤器的模拟实现

        布隆过滤器最常见的是string类型。 这里要给一个非类型模板参数N以确定开的空间有多大,这里我们写三个哈希函数。而字符串转整型的哈希函数有很多:
各种字符串Hash函数

这里我们就取里面效率较高的三个:

struct BKDRHash
{size_t operator()(const std::string& s){size_t value = 0;for (auto ch : s){value *= 31;value += ch;}return value;}
};struct APHash
{size_t operator()(const std::string& s){size_t hash = 0;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;}
};struct DJBHash
{size_t operator()(const std::string& s){size_t hash = 5381;for (auto ch : s){hash += (hash << 5) + ch;}return hash;}
};

2.3.1 布隆过滤器长度的设置

        关于长度的问题这里有专门的文章进行讲述:
详解布隆过滤器的原理
里面有一个公式:

        这里n我们是知道的,假设k是3,ln2约等于0.7,最后得到m=4.2*n,所以布隆过滤器多一个数据要开大约4.2个比特位,我们直接按加入一个数据开5个比特位算

template<size_t N,
class K = std::string,
class HashFunc1 = BKDRHash,
class HashFunc2 = APHash,
class HashFunc3 = DJBHash>
class BloomFilter
{
public:
private:std::bitset<N * 5> _bs;
};

2.3.2 插入操作

大致思路跟我们上面的位图一样,这里我们使用库里的函数bitset头文件:#include <bitset>而set函数库里面已经帮我们实现好了:

void set(const K& x)
{size_t idx1 = HashFunc1()(x) % (5 * N);size_t idx2 = HashFunc2()(x) % (5 * N);size_t idx3 = HashFunc3()(x) % (5 * N);_bs.set(idx1);_bs.set(idx2);_bs.set(idx3);
}

2.3.3 查找操作

这里只要有一处不在那么就返回false,全部都在才能返回true。

bool test(const K& x)
{size_t idx1 = HashFunc1()(x) % (5 * N);if (!_bs.test(idx1)){return false;}size_t idx2 = HashFunc2()(x) % (5 * N);if (!_bs.test(idx2)){return false;}size_t idx3 = HashFunc3()(x) % (5 * N);if (!_bs.test(idx3)){return false;}return true;
}

2.3.4 布隆过滤器删除

        布隆过滤器一般不能支持删除,因为一个位置可能被多个值映射,删除以后可能把别人的也删掉了。

那么我们能不能强制支持删除呢?

        我们可以去计数,有几个值映射计数器就是几,删除了就让当前位置的计数器--
但是使用计数又会有问题:因为不知道计数器的范围,所以不能开的太小的比特位,导致使用过多内存

2.4 布隆过滤器的应用

        给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和 近似算法。(query就是sql语句,可以理解为一个字符串。,也可能是网络请求url,也就是网址)

近似算法我们直接使用布隆过滤器,将一个文件的query语句放进布隆过滤器里,
然后另一个文件查找在不在就是交集。虽然有误判:不存在的也被当做交集。
但是作为近似算法还是可行的。
而精确算法就得用到前面的哈希切割。
同时把两个文件都切分成数个小文件,在编号相同的小文件查看交集即可,最后注意去重。

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

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

相关文章

使用Accelerate库在多GPU上进行LLM推理

大型语言模型(llm)已经彻底改变了自然语言处理领域。随着这些模型在规模和复杂性上的增长&#xff0c;推理的计算需求也显著增加。为了应对这一挑战利用多个gpu变得至关重要。 所以本文将在多个gpu上并行执行推理&#xff0c;主要包括&#xff1a;Accelerate库介绍&#xff0c;…

基于ArcGIS Pro、R、INVEST等多技术融合下生态系统服务权衡与协同动态分析实践应用

生态系统服务是指生态系统所形成的用于维持人类赖以生存和发展的自然环境条件与效用&#xff0c;是人类直接或间接从生态系统中得到的各种惠益。联合国千年生态系统评估&#xff08;Millennium ecosystem assessment&#xff0c;MA&#xff09;提出生态系统服务包括供给、调节、…

Day44力扣打卡

打卡记录 给小朋友们分糖果 II&#xff08;容斥原理 隔板法&#xff09; 链接 def c2(n):return n * (n - 1) // 2 if n > 1 else 0class Solution:def distributeCandies(self, n: int, limit: int) -> int:return c2(n 2) - 3 * c2(n - limit 1) 3 * c2(n - 2 * …

skywalking告警qq邮箱发送

首先开启发送接收qq邮箱的权限 开启之后&#xff0c;会让你发送信息&#xff0c;按着一系列操作&#xff0c;获得password &#xff08;授权码&#xff08;例如&#xff0c;qq开启SMTP授权码&#xff0c;qq授权码16位&#xff09;&#xff09; <!-- mail邮箱-->…

基于QT的俄罗斯方块游戏设计与实现

基于QT的俄罗斯方块游戏设计与实现 摘要&#xff1a;信息时代正处于高速发展中&#xff0c;而电子游戏已经成为人生活中或不可少的消磨工具之一。科技时代在不断地高速发展中&#xff0c;游戏相关编程设计也随着发展变得越来越重要&#xff0c; 俄罗斯方块游戏是一款古老传遍世…

共享充电宝被取代,共享WIFI项目将成市场趋势!

在创业领域如果有这样一个项目&#xff0c;你会选择哪一个&#xff1f;前者投资十万风险大&#xff0c;后者投资几千风险小。同样需要扫街地推&#xff0c;但产生的利润是相同的。相信100%的人会选择后者。实际上这两个项目前者就是共享电宝&#xff0c;后者就是共享WiFi项目。…

【hive-design】hive架构详解:描述了hive架构,hive主要组件的作用、hsql在hive执行过程中的底层细节、hive各组件作用

文章目录 一. Hive Architecture二. Metastore1. Metastore Architecture2. Metastore Interface 三. Compiler四. hive架构小结 本文主要讨论了 描述了hive架构&#xff0c;hive主要组件的作用详细描述了hsql在hive执行过程中的底层细节描述了hive各组件作用 一. Hive Archite…

U4_2:图论之MST/Prim/Kruskal

文章目录 一、最小生成树-MST生成MST策略一些定义 思路彩蛋 二、普里姆算法&#xff08;Prim算法&#xff09;思路算法流程数据存储分析 伪代码时间复杂度分析 三、克鲁斯卡尔算法&#xff08;Kruskal算法&#xff09;分析算法流程并查集-Find-set 伪代码时间复杂度分析 一、最…

Java 基础学习(三)循环流程控制与数组

1 循环流程控制 1.1 循环流程控制概述 1.1.1 什么是循环流程控制 当一个业务过程需要多次重复执行一个程序单元时&#xff0c;可以使用循环流程控制实现。 Java中包含3种循环结构&#xff1a; 1.2 for循环 1.2.1 for循环基础语法 for循环是最常用的循环流程控制&#xff…

android开发:安卓13Wifi和热点查看与设置功能

近日对安卓热点功能做了一些技术验证&#xff0c;目的是想利用手机开热点给设备做初始化&#xff0c;用的是安卓13&#xff0c;简言之&#xff1a; 热点设置功能不可用&#xff0c;不可设置SSID和密码&#xff0c;不可程序控制开启关闭&#xff0c;网上的代码统统都过时了Loca…

电脑资料删除后如何恢复?3个简单方法轻松恢复文件!

“我平常喜欢在电脑上保存很多学习资料&#xff0c;但由于资料太多&#xff0c;在清理电脑时我可能会误删一些比较有用的资料。想问问大家电脑资料删除后还有机会恢复吗&#xff1f;应该怎么操作呢&#xff1f;” 在数字化时代&#xff0c;很多用户都会选择将重要的文件直接保存…

winform 程序多语言

新建一个winform程序添加资源文件 在多语言的资源文件中设置key以及value设置button根据环境选择语言文件 namespace WindowsFormsMulLang {public partial class Form1 : Form{public Form1(){InitializeComponent();}public static ResourceManager rm new ResourceManager(…