哈希的应用——位图

简介: 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的,其本质也是一种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而已。而且位图一旦插入之后,他的搜索效率非常高。

          相关文章
          |
          自然语言处理 搜索推荐 算法
          M2GRL:一种用于全网规模推荐系统的多任务多视角图表示学习框架
          由阿里云开发者社区联合新零售智能引擎事业群共同打造的《KDD 论文精华解读》电子书重磅发布!覆盖推荐系统、图神经网络预训练、买家秀视频标题生成、在线电视剧的受众竞争力预测和分析等 10+ 内容,免费下载电子书感受科技的震撼!
          M2GRL:一种用于全网规模推荐系统的多任务多视角图表示学习框架
          |
          存储 算法 数据管理
          【C/C++ 基础算法】 C/C++ 位图算法的使用
          【C/C++ 基础算法】 C/C++ 位图算法的使用
          364 0
          |
          消息中间件 Java API
          面试官:如何实现链式调用?
          面试官:如何实现链式调用?
          744 0
          |
          4月前
          |
          存储 运维 关系型数据库
          从MySQL到云数据库,数据库迁移真的有必要吗?
          本文探讨了企业在业务增长背景下,是否应从 MySQL 迁移至云数据库的决策问题。分析了 MySQL 的优势与瓶颈,对比了云数据库在存储计算分离、自动化运维、多负载支持等方面的优势,并提出判断迁移必要性的五个关键问题及实施路径,帮助企业理性决策并落地迁移方案。
          |
          5月前
          |
          机器学习/深度学习 人工智能 算法
          通义WebSailor开源,检索性能登顶开源榜单!
          通义开源网络智能体WebSailor具备强大推理与检索能力,在复杂场景下表现优异,已登顶开源网络智能体榜单。其创新训练方法大幅提升了模型性能,适用于多领域复杂任务。
          706 0
          通义WebSailor开源,检索性能登顶开源榜单!
          |
          9月前
          |
          存储 数据采集 数据处理
          【数据结构进阶】位图
          位图是一种高效的数据结构,通过二进制的0和1表示数据的存在状态,适用于海量数据的压缩存储与快速检索。本文从概念、实现到应用场景全面解析位图。核心思想是将数据映射到位图的比特位,利用位运算实现O(1)时间复杂度的增删查操作。文章通过C++代码示例展示了位图的三大接口(set、unset、test)实现,并对比自定义位图与标准库`bitset`的异同。位图优点在于极高的时间和空间效率,但仅适用于整型数据。它为布隆过滤器等高级结构奠定了基础,在数据处理领域具有重要价值。
          657 1
          |
          机器学习/深度学习 数据可视化 数据挖掘
          数据集中存在大量重复值时,如何选择合适的分析方法?
          总之,当数据集中存在大量重复值时,需要综合考虑各种分析方法的特点和适用范围,根据具体的分析目标和数据情况选择合适的方法,或者结合多种方法进行综合分析,以获得准确、可靠的分析结果。
          529 65
          |
          机器学习/深度学习 自然语言处理 算法
          生成对抗网络是如何工作的
          【10月更文挑战第14天】生成对抗网络是如何工作的
          |
          SQL 数据库 索引
          SQL语句实现投影连接:技巧与方法详解
          在SQL数据库操作中,投影连接(Projection Join)是一种常见的数据查询技术,它结合了投影(Projection)和连接(Join)两种操作
          |
          编译器 数据库 索引
          数据结构篇:树形数据结构的基本概念及其遍历方法
          数据结构篇:树形数据结构的基本概念及其遍历方法
          564 0