【C++进阶】哈希的应用之位图和布隆过滤器

位图和布隆过滤器

  • 一,位图
    • 1. 实现
    • 2. 位图的应用
  • 二,布隆过滤器
    • 1. 使用场景
    • 2. 模拟实现
  • 三,海量数据面试题
    • 哈希切分
  • 四,总结

这一节我们来看哈希的应用

一,位图

先来看一个面试题
在这里插入图片描述
这里如果用unordered_set来解决,是不可取的,因为一个整型4个Byte,40亿个整型那就是16个G,把这16个G直接放进内存是不合理的,所以就要用到位图。
在这里插入图片描述

位图和哈希表相比,就是将每个数据元素映射到每一个比特位上。适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。

1. 实现

位图的实现比较简单,下面是位图bitset的一些常用接口:
在这里插入图片描述
首先我们要构造位图,确定好要开的空间大小
这里的构造需要传入所需要的比特位数,然后我们在实现时根据传入的N来确定相应的比特位
在这里插入图片描述
这里我们可以先写出bitset的框架:

template<size_t N>//非类型模板参数---表示需要多少个比特位去映射
class bitset {
public:bitset() {//构造函数根据需要的比特位来开相应的数组_bits.resize((N >> 5) + 1, 0);//除以2的5次方相当于右移5位}//...
private:vector<int> _bits;
};

这里我们也是只模拟实现主要的接口:
在这里插入图片描述
set的作用是将一个整型放入位图中,映射的时候我们先找到要映射的是第几个字节,然后再计算这个字节的第几个比特位,将这个比特位置为1即可

在这里插入图片描述

reset的作用是将数据从位图中删除,也就是将映射的比特位置为0

void set(size_t x) {//将映射到的位置置为1size_t i = x / 32;//i表示映射在数组的第几个整型中size_t j = x % 32;//j表示映射在第i个整型的第j位上_bits[i] |= (1 << j);//将映射到的位置置为1---用相应的数去 或等 (任何数和1或都为1,和0或为任何数)
}void reset(size_t x) {//将映射的位置置为0size_t i = x / 32;size_t j = x % 32;_bits[i] &= ~(1 << j);//将映射的位置置为0---将相应的数取反去 与等 (任何数和1与为如何数,和0与都为0)
}

位图解决的是在不在的问题,当然位图这种结构也有一个扩展的问题,就是找到第一次出现的数的这类问题,对于这类问题,其实就是用两个位图来存放一个数
在这里插入图片描述
具体的代码可以进入我的gitee仓库查看: 位图的实现

2. 位图的应用

对于位图来说,其只能存储整型的数据,所以其常见的应用就是如下几个:
在这里插入图片描述

二,布隆过滤器

1. 使用场景

对于位图而言,其只能处理整型的数据,如果要处理字符串类型呢,就无法处理了

我们如果简单地将字符串转换为整型,再映射到对应的位,那么就会出现多个字符串映射到同一个位的问题,因为整型最大只有32位,但是字符串可以有很多位
在这里插入图片描述
为了解决这样的问题我们可以让一个字符串映射到多个比特位上
在这里插入图片描述
这样的结构也会导致判断一个字符串不在是准确的,因为只要有一个比特位为0就是不在,判断在是不准确的,因为哈希函数存在误判。

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

至于为什么叫布隆过滤器,我们可以看下面的使用场景进行理解:
假设有一个注册页面需要你来创建用户名,如果这个用户名已经被创建,则需要换一个名称,那么面对大量的数据情况下,如果查找这个创建的用户名是否已经被申请了呢?总不可能每次都在后台的服务器上一个个查找吧,这时就可以借助布隆过滤器了,如果查找这个名称存在,则不可以创建,如果不在,则可以创建。这种场景下是允许误判的,因为判断一个不在的比误判一个存在的要合理
在这里插入图片描述

2. 模拟实现

下面我们来模拟实现一下,布隆过滤器底层用的其实也是位图,所以实现时我们直接用位图的接口即可
这里默认处理的类型是string,所以要有对应的哈希函数来将字符串转换为整型,这里我们直接用三种哈希函数来转换。

//这三个哈希函数造成的哈希冲突是最少的
struct BKDRHash
{size_t operator()(const string& key){// BKDRsize_t hash = 0;for (auto e : key){hash *= 31;hash += e;}return hash;}
};struct APHash
{size_t operator()(const string& key){size_t hash = 0;for (size_t i = 0; i < key.size(); i++){char ch = key[i];if ((i & 1) == 0){hash ^= ((hash << 7) ^ ch ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}}return hash;}
};struct DJBHash
{size_t operator()(const string& key){size_t hash = 5381;for (auto ch : key){hash += (hash << 5) + ch;}return hash;}
};template<size_t N, class K = string,
class Hashfunc1 = BKDRHash,
class Hashfunc2 = APHash,
class Hashfunc3 = DJBHash>//这里默认处理的是sting字符串,三个仿函数是哈希函数,将string映射成整型
class BloomFilter {
public:void set(const K& key){//将字符串经过哈希得到三个整型size_t hash1 = Hashfunc1()(key) % N;//仿函数匿名对象,%N是为了不超出Nsize_t hash2 = Hashfunc2()(key) % N;size_t hash3 = Hashfunc3()(key) % N;//再将这三个整型分别映射到三个比特位_b.set(hash1);_b.set(hash2);_b.set(hash3);}
private:bitset<N> _b;
};

完整代码可以参考这里:布隆过滤器

三,海量数据面试题

哈希切分

有这样一个问题
在这里插入图片描述
这里有两个100亿的查询字符串query,是不可能将这两个字符串放进内存直接查询的,所以就要做到哈希切割
在这里插入图片描述
这样切分后,每个小文件都是相同的数据元素,找交集时会在相同的文件中查找

但是如果切分后的小文件还是很大怎么办

切分后的小文件很大的原因有两个
1.一个文件中都是相同的query
2.这个文件中很多不同的query
如果遇到这种问题,则继续将这个小文件放入set中,如果是第一种情况,那么在放入set中时,重复的元素不会被存入
如果是第二种情况,则继续进行哈希切分处理。

四,总结

哈希这部分我们也算是讲解完了,哈希的用途还是非常的广。希望大家可以对哈希有一个深入的理解。C++学到这里其实也走过了大部分了,但是在这里我想说基础还是很重要的,基础越牢固,后面的学习才会更快。希望大家都可以打好基础,对C++有深入的学习。

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

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

相关文章

C++11可变模板参数:海纳百川的Args

目录 一、可变模板参数的概念及功能 1.1Args的概念与使用 1.2获取args中的参数 二、emplace可变模板参数的实际应用 三、逗号表达式展开参数包 一、可变模板参数的概念及功能 1.1Args的概念与使用 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板…

二维码门楼牌管理应用平台建设:物业缴费的数字化革新

文章目录 前言一、物业缴费的数字化革新二、在线缴费功能的实现三、智能化缴费管理的优势四、面临的挑战与未来展望五、结语 前言 随着科技的不断进步&#xff0c;二维码门楼牌管理应用平台已成为物业管理的新趋势。在这样一个平台上&#xff0c;物业缴费的数字化革新不仅提高…

【计算机网络】TCP协议可靠传输保证(序列号/确认应答机制、超时重传、最长消息长度、滑动窗口控制、拥塞控制)

TCP协议可靠传输 1.序列号确认应答机制2.超时重传3.最长消息长度4.滑动窗口控制5.拥塞控制 1.序列号确认应答机制 这个机制类似于问答的形式。比如在课堂上老师会问你“明白了吗&#xff1f;”&#xff0c;假如你没有隔一段时间没有回应或者你说不明白&#xff0c;那么老师就会…

橘子学JDK之JMH-03(@State)

这里我们来搞官方的第三个案例&#xff0c;引入新的注解State。 一、案例三代码 package com.levi;/*** Description:* Author: Levi* Date: 2024/4/8 18:44*/import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.R…

【YOLOV8】项目目录重点部分介绍和性能评估指标

目录 一 项目目录重点部分介绍 二 性能评估指标 一 项目目录重点部分介绍 1 ultralytics

windows环境变量滥用维权/提权

0x01 前提 通过滥用系统的路径搜索机制来欺骗高权限用户执行看似合法的系统二进制文件&#xff0c;实际上是恶意的代码或程序&#xff0c;从而导致升权限并执行恶意操作。 攻击的关键前提&#xff1a; 路径搜索顺序&#xff1a; 当用户在命令行或程序中执行一个命令时&#x…

kafka 高吞吐设计分析

说明 本文基于 kafka 2.7 编写。author blog.jellyfishmix.com / JellyfishMIX - githubLICENSE GPL-2.0 概括 支撑 kafka 高吞吐的设计主要有以下几个方面: 网络 nio 主从 reactor 设计模式 顺序写。 零拷贝。 producer producer 开启压缩后是批量压缩&#xff0c;bro…

【Qt】:常用控件(七:输入类控件)

常用控件 一.Combo Box&#xff08;下拉框&#xff09;二.Spin Box&#xff08;微调框&#xff09;三.ate Edit&Time Edit&#xff08;日期微调框&#xff09;四.Dial&#xff08;旋钮&#xff09;五.Slider&#xff08;滑动条&#xff09; 一.Combo Box&#xff08;下拉框…

738.单调递增的数字

// 定义一个名为Solution的类 class Solution { public:// 定义公共成员函数&#xff1a;计算并返回大于等于输入整数N且其各位数字非降序排列的最小整数int monotoneIncreasingDigits(int N) {// 将整数N转换成字符串形式&#xff0c;方便操作每一位数字string strNum to_str…

23linux 自定义shell文件系统

打印环境变量&#xff0c;把当前子进程所有环境变量打印出来 环境变量也是一张表&#xff08;指针数组以null结尾&#xff0c;最后条件不满足就退出了 &#xff09; 用子进程调用 结论1 当我们进行程序替换的时候 &#xff0c;子进程对应的环境变量&#xff08;子进程的环境变…

Mybatis执行器(Executor)

Executor简介 Executor Executor是MyBatis的核心接口之一&#xff0c;其中定义了数据库操作的基本方法。在实际应用中经常涉及的SqlSession接口的功能&#xff0c;都是基于Executor接口实现的。 BaseExecutor BaseExecutor是一个实现了Executor接口的抽象类,它实现了Execut…

Yolov8-pose关键点检测:特征融合 | CAMixing:卷积-注意融合模块和多尺度提取能力 | 2024年4月最新成果

💡💡💡本文独家改进:CAMixingBlock更好的提取全局上下文信息和局部特征,包括两个部分:卷积-注意融合模块和多尺度前馈网络; 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect前面,增强detect提取能力; 提供多种改进方…

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 限幅和滤波&#xff08;Clipping and Filtering&#xff09; 原理简介 限幅和滤波是一种基础且直观的方法&#xff0c;用于降低OFDM信号的PAPR。在限幅阶段&#xff0c;信号的幅度在达到设定阈值时会被削减&#xff0c;…

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

皮具5G智能制造工厂数字孪生可视化平台&#xff0c;推进企业数字化转型。随着信息技术的快速发展&#xff0c;数字化转型已成为企业提升竞争力、实现可持续发展的关键路径。皮具行业&#xff0c;作为一个传统的手工制造业&#xff0c;正面临着巨大的市场变革和技术挑战。如何在…

红队打靶:holynix打靶流程-文件包含-文件上传-修改伪设备提权(vulnhub)

目录 开头 1.主机发现和端口扫描 2.80端口-万能密码-文件泄露 sql注入万能密码 文件泄露-读取/etc/passwd文件 sqlmap POST注入| SQL注入实现越权 | 水平越权 最后构造的sql语句,为什么这么构造嘞&#xff1f; 3.文件上传、文件解析漏洞利用 浏览器怎么访问家目录啊&…

C语言指针—指针和指针类型

指针是什么&#xff1f; 指针是什么&#xff1f; 指针理解的2个要点&#xff1a; 指针是内存中一个最小单元的编号&#xff0c;也就是地址 平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放内存地址的变量 总结&#xff1a;指针就是地址&#xff0c;口…

Windows深度学习环境----Cuda version 10.2 pytorch3d version 0.3.0

Requirements Python version 3.8.5Pytorch version: pytorch1.6.0 torchvision0.8.2 torchaudio0.7.0 cudatoolkit10.2.89pytorch3d version 0.3.0Cuda version 10.2 感觉readme文件里的不适配&#xff0c;跟pytorch官网不同 以前的 PyTorch 版本 |PyTorch的 # CUDA 10.2 c…

充电桩项目,开源啦!

好&#xff0c;我是田哥 很多人&#xff0c;最近都在关注我的充电桩项目&#xff0c;之前建了一个微服务架构的项目&#xff0c;也有单体项目的代码开源。 今天&#xff0c;我把最新版微服务架构的充电桩项目源代码开源。 充电桩的输入端与交流电网直接连接&#xff0c;输出端都…

WindowServer2019远程桌面无法连接问题及处理方法

WindowServer2019远程桌面无法连接问题及处理方法 文章目录 WindowServer2019远程桌面无法连接问题及处理方法1. 问题描述1. 连接问题2. 原因分析 2. 解决方法1. 零时解决方法2. 永久解决方法1. 打开注册表编辑器2. GracePeriod的权限权限设置3. 删除REG_BINARY4. 重启 1. 问题…