哈希的应用——位图

简介: 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的,其本质也是一种hash。但是其占用空间很少。

 

✅<1>主页::我的代码爱吃辣

📃<2>知识讲解:数据结构——位图

☂️<3>开发环境:Visual Studio 2022

💬<4>前言:所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的,其本质也是一种hash。但是其占用空间很少。

目录

一.位图概念

二.STL库中的位图

三.模拟实现位图

1.构造函数

2.set

3.reset

4.test

四.完整代码

五.位图的引用


image.gif编辑

一.位图概念

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

面试体:

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

这40亿个数中。【腾讯】

分析:首先这道题的40亿个无符号整数,如果直接存储到内存的话需要16G的内存,我们首先想到的是使用set,或者unordered_set,但是这里仅仅是数据就已经存储由将近16G大小了,如果我们存放到容器里面,加上一些存储的消耗(指针),实际消耗的内存更是远超16G,这就导致了一般的计算机的内存和普通数据结构来对这些数据进行处理。

所以我们引用一个新的数据结构,就是位图。简单来说仅仅使用一个比特位来标识数据在不在的状态。

    1. 遍历,时间复杂度O(N)
    2. 排序(O(NlogN)),利用二分查找: logN
    3. 位图解决

    数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一
    个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0
    代表不存在
    。比如:

    image.gif编辑

    位图也是利用了哈希映射的思想,而且采用的是直接定值映射的方法,最大的区别是位图仅仅使用一个比特位来标识数据是否存在,hash是需要对数据进行存储的。

    二.STL库中的位图

    STL库中也给我们提供了位图结构bitset,头文件<bitset>

    image.gif编辑

    简单介绍几个核心接口:

      • set():将数据插入位图。
      • reset():将数据从位图中挪去。
      • test():判断数据在不在位图中。
      int main()
      {
        bitset<10000> bit;
        int arr1[] = { 1,15,3,6,8,9,4,23 };
        int arr[] = { 45,12,32,3,6,35,12,78,94,23,62,54 };
        //将arr数据插入位图
        for (auto e : arr)
        {
          bit.set(e);
        }
        //检查arr1,时候出现在位图中
        for (auto e : arr1)
        {
          cout << e << ":" << bit.test(e) << endl;;
        }
        return 0;
      }

      image.gif

      image.gif编辑

      三.模拟实现位图

      C/C++中没有单个比特位类型,最小的也是单个字节的char,所以我们只能使用,char配合vector来存储位图结构。

      在定义位图的时候我们可以控制定义的位图存储位数,所以位图的设计我们可以使用一个非类型模板参数来控制。

      template<size_t N>
      class BitSet
      {
      public:
      private:
        vector<char> _map;
      };

      image.gif

      1.构造函数

      假如我们需要开85个比特位,而我们因为最小的开辟单元是char即八比特位,所以如果剩下的不足八比特位,我们仍然按照一个char开辟。

      BitSet()
        {
              //不足一个字节时,就按一个字节开辟,并且全部初始化0
          _map.resize((N / 8) + 1, 0);
        }

      image.gif

      2.set

      找到需要插入的比特位共需两步:

        1. 找到所在char
        2. 找到所在的比特位
        3. 使用位运算插入

        image.gif编辑

        void set(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            _map[i] |= 1 << j;
          }

        image.gif

        3.reset

        reset与set在查找位置时,步骤一致仅仅是在最后一步换成使用位运算将最后一位变为0.

        image.gif编辑

        void reset(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            _map[i] &= ~(1 << j);
          }

        image.gif

        4.test

        先找到需要判断的位置,在使用位运算判断。

        image.gif编辑

        bool test(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            return _map[i] & (1 << j) ;
          }

        image.gif

        四.完整代码

        template<size_t N>
        class BitSet
        {
        public:
          BitSet()
          {
            _map.resize((N / 8) + 1, 0);
          }
          void set(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            _map[i] |= 1 << j;
          }
          void reset(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            _map[i] &= ~(1 << j);
          }
          bool test(const int num)
          {
            size_t i = num / 8;
            size_t j = num % 8;
            return _map[i] & (1 << j) ;
          }
        private:
          vector<char> _map;
        };

        image.gif

        测试:

        image.gif编辑

        五.位图的引用

          1. 快速查找某个数据是否在一个集合中
          2. 排序 + 去重
          3. 求两个集合的交集、并集等
          4. 操作系统中磁盘块标记

          回顾刚才的面试题:

          我们将40亿的整数全部存入位图,仅仅才占有512M而已。而且位图一旦插入之后,他的搜索效率非常高。

          相关文章
          |
          7月前
          |
          存储 数据处理 C++
          哈希的应用--位图和布隆过滤器(上)
          位图 1. 位图概念 位图(Bitset)是一种数据结构,用于表示一组布尔值,其中每个元素通常对应于一个位或一个二进制值,可以存储0或1。位图在计算机科学和计算机工程中经常用于各种应用,特别是
          |
          7天前
          |
          存储 算法 C++
          【C++高阶(六)】哈希的应用--位图&布隆过滤器
          【C++高阶(六)】哈希的应用--位图&布隆过滤器
          |
          7月前
          |
          存储 算法 Linux
          哈希的应用--位图和布隆过滤器(下)
          布隆过滤器 在上面我们用位图很好的解决了多重整数高效查询的问题,那么我们在面对字符串时,该如何解决呢? 1. 布隆过滤器的提出 布隆过滤器(Bloom Filter)是由布隆在1970年提出的,它是一种空间效率高、查询速度快的数据结构,主要用于判断一个元素是否属于一个集合。布隆过滤器的提出解决了在大规模数据集中进行
          |
          3月前
          |
          存储 Serverless
          位图和布隆过滤器
          位图和布隆过滤器
          |
          4月前
          |
          存储 算法 搜索推荐
          位图与布隆过滤器
          位图与布隆过滤器
          47 0
          |
          5月前
          |
          存储 算法 Linux
          C++ 哈希的应用【位图】
          C++ 哈希的应用【位图】
          28 0
          |
          5月前
          |
          算法
          【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
          【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
          |
          6月前
          |
          存储 机器学习/深度学习 算法
          C++位图和布隆过滤器
          C++位图和布隆过滤器
          |
          11月前
          |
          算法 数据库 C++
          【C++】哈希(位图,布隆过滤器)(二)
          【C++】哈希(位图,布隆过滤器)
          58 0
          |
          11月前
          |
          存储 算法 大数据
          【C++】哈希(位图,布隆过滤器)(一)
          【C++】哈希(位图,布隆过滤器)
          78 0