位图和布隆过滤器:位图

简介: 位图和布隆过滤器:位图

在《unordered_mapunordered_set》 中提到过:

哈希是一种思想,通过哈希函数将数据转化为一个或多个整型 —— 映射关系;通过这种映射关系,可以做到以 O(1) 的时间复杂度查找数据。

本文即将介绍的 位图布隆过滤器 就是两个非常典型的哈希思想的应用成果,可以在应对海量数据问题 且 做到极大程度节省空间的同时,快速判断 一个元素 是否在 位图 或 布隆过滤器 中

一、位图

1.1 位图的概念

在直接给出位图的概念之前,我们先温习几个常识:

  • 1 int == 4 byte
  • 1 byte == 8 bit ——> 1 int == 32 bit

也就是说,假设我们有 10 个位于 [0, 32) 的整数,仅需 1 个 int 就可以将这些数据标记(在保证数据范围的情况下,即使数据量更大一些也没问题)。

位图的概念:

各个比特位上的数据默认为 0 —— 不存在,遍历数据的过程中,将数据对应位置的 0 修改为 1 —— 存在;再判断某个整数是否存在时,仅须根据其对应位置上的状态(0 或 1)即可得出。

图中 “53 在 32 右边” 的情形并不绝对,与机器的大小端有关。无论你的设备是大端机还是小端机,“1 << 21” —— 左移 都能保证把 “1” 往数据高位移动

进一步延伸,面对这样一个场景:

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。

试图通过 排序 + 二分 的办法解决,显然不靠谱 —— 仅存下 40 亿个整数大约需要 16 GB 内存

面对海量整型数据,判断某个整数存在与否 的场景下,位图具有无可比拟的优势 —— 占用的空间小且能够快速查找

一个非常重要的问题:位图应该开多大的空间? 具体要开多大,不是由数据的个数决定,而是由数据的范围决定

代码:
template<size_t N> // 非类型模板参数
    class bitset 
    {
    public:
        bitset()
        {
            _bs.resize(N/32 + 1); // 开 (N/32 + 1) 个 int 类型空间
        }
        void set(size_t n) // 将 n 对应的位置状态修改为 1
        {
            size_t i = n / 32;
            size_t j = n % 32;
            _bs[i] |= (1 << j);
        }
        void reset(size_t n) // 将 n 对应的位置状态修改为 0
        {
            size_t i = n / 32;
            size_t j = n % 32;
            _bs[i] &= ~(1 << j);
        }
        bool test(size_t n) // 判断 n 是否存在
        {
            size_t i = n / 32;
            size_t j = n % 32;
            return _bs[i] & (1 << j);
        }
    private:
        vector<int> _bs;
    };

位图代码逻辑本身很简单,诸位读者要理解各个函数中位运算的经义。

PS: STL 库中 bitset 是在栈区上开空间,我们实现的位图在堆区上开空间。

1.2 切分思想

还是上面那个的场景(40 亿个不重复整数),我们进一步对可使用内存的大小进行限制 —— 只能使用 256 MB 。

这会带来一个结果:我们无法一次性把这么多整数存入位图 —— 40 亿个不重复整数大约 500 MB。

把这 40 亿个整数分成两个区间:[0, 2 ^ 31)[2 ^ 31, 2 ^ 32) 。(2 ^ 31 与 2 ^ 32 均为数学运算,C++ 中 ^ 为 异或)

先对 [0, 2 ^ 31) 范围内的整数进行 set() 和 test() ,处理完后将位图置空,再处理 [2 ^ 31, 2 ^ 32) 部分。

相关文章
|
存储 数据处理 C++
哈希的应用--位图和布隆过滤器(上)
位图 1. 位图概念 位图(Bitset)是一种数据结构,用于表示一组布尔值,其中每个元素通常对应于一个位或一个二进制值,可以存储0或1。位图在计算机科学和计算机工程中经常用于各种应用,特别是
|
5月前
|
存储 算法 数据挖掘
【C++】位图
【C++】位图
50 1
|
7月前
|
存储 监控 算法
【C++】哈希(位图、布隆过滤器)
【C++】哈希(位图、布隆过滤器)
|
存储 算法 Linux
哈希的应用--位图和布隆过滤器(下)
布隆过滤器 在上面我们用位图很好的解决了多重整数高效查询的问题,那么我们在面对字符串时,该如何解决呢? 1. 布隆过滤器的提出 布隆过滤器(Bloom Filter)是由布隆在1970年提出的,它是一种空间效率高、查询速度快的数据结构,主要用于判断一个元素是否属于一个集合。布隆过滤器的提出解决了在大规模数据集中进行
|
7月前
|
存储 Serverless
位图和布隆过滤器
位图和布隆过滤器
|
7月前
|
存储 算法 搜索推荐
位图与布隆过滤器
位图与布隆过滤器
74 0
|
7月前
|
存储 算法 Linux
C++ 哈希的应用【位图】
C++ 哈希的应用【位图】
63 0
|
存储 机器学习/深度学习 算法
C++位图和布隆过滤器
C++位图和布隆过滤器
|
存储 C++ 容器
哈希的应用——位图
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的,其本质也是一种hash。但是其占用空间很少。
|
算法 数据库 C++
【C++】哈希(位图,布隆过滤器)(二)
【C++】哈希(位图,布隆过滤器)
95 0