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

【数据结构与算法】位图 布隆过滤器 海量数据问题处理 哈希切分

文章目录

  • Ⅰ. 位图
    • 一、问题引入
    • 二、位图概念
    • 三、位图的模拟实现
      • set 函数:将 x 位置处的比特位设为 1
      • reset 函数:将 x 位置处的比特位设为 0
      • test 函数:检查 x 位置处的比特位是否为 1
    • 四、位图的应用
    • 五、常见面试题
      • ① 给定100亿个整数,设计算法找到只出现一次的整数?
      • ② 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
      • ③ 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
  • Ⅱ. 布隆过滤器
    • 二、布隆过滤器的提出
    • 二、布隆过滤器的概念
    • 三、布隆过滤器的结构
    • 四、布隆过滤器的模拟实现
      • ① 插入函数 Set
      • ② 查找函数 Test
      • ③ 布隆过滤器的删除
    • 五、布隆过滤器的优点
    • 六、布隆过滤器的缺点
    • 七、布隆过滤器的应用场景
    • 八、布隆过滤器的面试题
  • Ⅲ. 布谷鸟过滤器
    • 一、布谷鸟过滤器由来
    • 二、布谷鸟哈希
    • 三、布谷鸟哈希的问题
    • 四、布谷鸟哈希的优化
    • 五、布谷鸟过滤器
    • 六、特殊的hash函数
  • Ⅳ. 哈希切分
      • 哈希切分的一道题
  • Ⅳ. 拓展阅读

在这里插入图片描述

Ⅰ. 位图

一、问题引入

​ 这里有道题:给 40 亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这 40 亿个数中。这里一共有三种方法:

  1. 遍历,时间复杂度 O(N)
  2. 先排序 O(NlogN),然后利用二分查找:O(logN)

​ 很明显发现前两种方法虽然可行,但是对于 40 亿个整数来说,内存开销是十分的大的,因为 40 亿个整数相当于是 16GB 左右,这个时候也更不可能去使用红黑树这些数据结构来解决,毕竟红黑树这些数据结构本身就带有一些负载的消耗(旋转),所以我们这里给出了第三种方法:位图!

二、位图概念

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

​ 比如上面的面试题,要我们开 40 亿个整数,并且判断一个数是否在这其中,那么我们只需要开辟 500MB 的空间大小,因为我们这里每个比特位代表一个数字存不存在的状态,比如 0 代表不存在,1 代表存在,那么一个比特位就足够啦,于是只需要开原本需要 16GB1/32 即可,也就是 500MB!这就很巧妙的解决了空间问题!

​ 而至于时间问题,查找某个数字的时候,位图也是通过某个数字的对应映射关系查找的,也就是通过哈希!所以时间复杂度为 O(1)

在这里插入图片描述

三、位图的模拟实现

​ 首先我们先把其框架搭出来:

// BitSet.h
#include <iostream>
#include <vector>
namespace liren
{class BitSet{private:std::vector<char> _bits; };
}

这里很奇怪哦,用到的是 vector 里面存的 char,为什么呢?

​ 仔细想一想,c++ 中最小的存储单位就是 char,由于我们要的是按比特位来识别数字,所以我们这里就用 char 类型来表示 8 个比特位,也就是 8 个数字,这样子也方便我们后面的位运算!(用 int 类型来存储也可以,但是一共有 32 个比特位,相比于 char 的话会更难控制一些,所以这里选用 char


​ ❓ 那么我们接下来的拷贝构造函数中如何来初始化呢?

这里我们用模板参数 N 来代表要初始化的比特位个数,那么问题又来了,数组开多大的空间呢❓

​ 🌛 由于我们数组中存放的类型是 char 类型,所以我们要得到 N 个比特位的话,则要 resize(N / 8),这里还有一个细节,就是还要多加一,因为假设 N10 的话,那么 N / 8 其实还是 1,那么我们开出来的就只有一个 char 也就是 8 个比特位,但是 N10 啊,所以为了保险起见,我们每次多开一个 char 的空间!也就是 resize(N / 8 + 1)

// BitSet.h
#include <iostream>
#include <vector>
namespace liren
{// N代表要存放的比特位数量template <size_t N>class BitSet{public:// 构造函数BitSet(){// 每次多开一个字节,并初始化为0_bits.resize(N / 8 + 1, 0);}private:std::vector<char> _bits; };
}

下面我们就来实现位图的几个主要的接口函数:(注意这里vs是小端,大端的实现略有不同

set 函数:将 x 位置处的比特位设为 1

​ 方法:先获取到 x 的位置,然后 按位或x 处比特位为 1 的数即可。

// 将x位置处的比特位设为1
void set(size_t x)
{// 先获取x的位置size_t i = x / 8;size_t j = x % 8;// 接着让x处的比特位(按位或)上(只有x处为1的数)// 注意这里vs是小端存储,注意方向_bits[i] |= (1 << j);
}

reset 函数:将 x 位置处的比特位设为 0

​ 方法:先获取到 x 的位置,然后让 x 处的比特位 按位与(&)上 x 处比特位为 0 其他位为 1 的数即可。

// 将x位置处的比特位设为0
void reset(size_t x)
{// 先获取x的位置size_t i = x / 8;size_t j = x % 8;// 接着让x处的比特位(按位与)上(只有x处为0的数)// 注意这里vs是小端存储,注意方向_bits[i] &= (~(1 << j));
}

test 函数:检查 x 位置处的比特位是否为 1

// 检查x位置处的比特位是否为1
bool test(size_t x)
{// 先获取x的位置size_t i = x / 8;size_t j = x % 8;// 接着让x处的比特位(按位与)上(只有x处为1的数)return _bits[i] & (1 << j);
}

​ 测试代码:

// test.cpp
#include "BitSet.h"int main()
{liren::BitSet<20> t;t.set(10);std::cout << t.test(10) << std::endl;t.reset(10);std::cout << t.test(10);return 0;
}

​ 接下来我们尝试着来解决上面遗留的面试题:

int main()
{// 40亿个整数,我们只需要开500MB的比特位即可// 但是为了保证int的范围都被包括,我们要开42亿整数空间的大小// 也就是unsigned的最大值// 但其实这里我们直接利用十六进制表示即可开unsigned的最大值//liren::BitSet<-1> b; 这种写法会报错liren::BitSet<0xffffffff> b;b.set(1314);std::cout << b.test(1314) << std::endl;b.reset(1314);std::cout <
http://www.xdnf.cn/news/3610.html

相关文章:

  • AdaBoost算法详解:原理、实现与应用指南
  • C++异常处理
  • terraform 删除资源前先校验资源是否存在关联资源
  • 数字智慧方案6172丨智慧医院扩建信息化整体规划方案(60页PPT)(文末有下载方式)
  • LiteOS与SLE透传实战案例
  • 数据结构-树(二叉树、红黑、B、B+等)
  • kes监控组件安装
  • 传感器的精度,灵敏度等概念介绍
  • MySQL 高可用架构设计:电商系统的实践与优化
  • 完美中国制度流程体系建设(70页PPT)(文末有下载方式)
  • 1996-2022年全国31省ZF干预度数据/财政干预度数据(含原始数据+计算过程+结果)
  • Linux从入门到精通:全面掌握基础命令与高效操作实战指南
  • ES6函数、对象和面向对象扩展
  • 攻防世界 - Misc - Level 8 | traffic
  • 【2025五一数学建模竞赛B题】 矿山数据处理问题|建模过程+完整代码论文全解全析
  • AI翻译通APP:智能翻译,轻松应对多场景需求
  • 人工智能的前世今生
  • 【笔记】深度学习模型训练的 GPU 内存优化之旅④:内存交换与重计算的联合优化篇
  • OCaml中的object和class基础知识介绍
  • LeetCode 978 最长湍流子数组 题解
  • 掉馅饼,八分之一到二分之一:《分析模式》漫谈59
  • OpenAI已经紧急修复了GPT-4o存在的过度讨好用户的问题,现已将系统回滚到之前的旧版本。
  • 蓝桥杯获奖后心得体会
  • 蓝莓的功效与作用 蓝莓叶黄素对眼睛真的有用吗
  • # 交通标志识别:使用卷积神经网络的完整实现
  • 我试用了50个AI工具——AI正在如何改变设计方式
  • 高并发场景下的MySQL生存指南
  • 进程与线程:04 内核线程
  • 蓝桥杯比赛
  • 2022 年 12 月大学英语四级考试真题(第 1 2 3 套)——解析版——篇章题