【数据结构】哈希经典应用:位图——[深度解析](8)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【数据结构】哈希经典应用:位图——[深度解析](8)

一.位图的基本概念

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

二.位图的原理

  • 哈希—— 直接定址法
  • 例:
  • 在实际场景中,我们的机器一般是 小端机(从左到右,从大到小排布)
  • 所以真正的场景一般如下:
  • 小端机性质 证明:

三.位图(bitset)的代码实现(逐过程解读)

【1】位图的文档查看

  • 我们可以重点关注红圈圈出的三个位图常用函数

【2】把X映射的那个标记成1——对应biteset中的set

【3】把X映射的那个标记成0——对应biteset中的reset

【4】判断某位是1还是0——对应biteset中的test

【5】位图的完整实现

#include<vector>
namespace bit
{
  template<size_t N>
  class bitset
  {
  public:
    bitset()
    {
      _a.resize(N / 32 + 1);//位图的初始化,确定分为多少块
    }
    // x映射的那个标记成1
    void set(size_t x)
    {
      size_t i = x / 32;
      size_t j = x % 32;
      _a[i] |= (1 << j);
    }
    // x映射的那个标记成0
    void reset(size_t x)
    {
      size_t i = x / 32;
      size_t j = x % 32;
      _a[i] &= (~(1 << j));
    }
    bool test(size_t x)
    {
      size_t i = x / 32;
      size_t j = x % 32;
      return _a[i] & (1 << j);
    }
  private:
    vector<int> _a;
  };
}

四.位图的经典应用场景

【※】对数据大小&转换的基本概念

  • 1G =1024 MB=10241024 BK=10241024*1024 Byte= 2^30 byte = 10亿+ byte
  • 例:我们判断40亿个整数需要多少G呢?
    分析:40亿个int,160亿byte,根据10亿byte对应1G,160亿byte对应16G

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

  • 分析:常规思路是遍历/排序+二分查找
  • 遍历的时间复杂度是O(N),排序(O(NlogN))+二分查找 logN
  • 显然对于40亿无符号整数来说,需要占用16G,占用资源过于庞大,不妥
  • 快速判断在不在,显然是位图经典场景,利用位图解决:
  • 数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:

【2】给定100亿个整数,设计算法找到只出现一次的整数

  • 分析:我们可以用两个位图来控制,我们可以这样设计
  • 代码展示设计思路如图所示:
template<size_t N>
  class twobitset
  {
  public:
    void set(size_t x)
    {
      // 00 -> 01
      if (!_bs1.test(x) && !_bs2.test(x))
      {
        _bs2.set(x);
      } // 01 -> 10
      else if (!_bs1.test(x) && _bs2.test(x))
      {
        _bs1.set(x);
        _bs2.reset(x);
      }
      // 本身10代表出现2次及以上,就不变了
    }
    bool is_once(size_t x)
    {
      return !_bs1.test(x) && _bs2.test(x);
    }
  private:
    bitset<N> _bs1;
    bitset<N> _bs2;
  };

【3】位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

  • 此题的设计思路与上面的【2】基本一致,设计上要稍作改动:
  • 代码展示设计思路如图所示:
template<size_t N>
  class twobitset
  {
  public:
    void set(size_t x)
    {
      // 00 -> 01
      if (!_bs1.test(x) && !_bs2.test(x))
      {
        _bs2.set(x);                        //出现一次
      } // 01 -> 10
      else if (!_bs1.test(x) && _bs2.test(x))
      {
        _bs1.set(x);
        _bs2.reset(x);                    //出现两次
      }// 10 -> 11
      else if (_bs1.test(x) && !_bs2.test(x))
      {
        _bs2.set(x);                      //出现三次
      }
      // 此外代表出现3次及以上,就不变了
    }
    bool max_two(size_t x)
    {
      return (_bs1.test(x) && !_bs2.test(x))||(!_bs1.test(x) && _bs2.test(x));   //10 或者 01
    }
  private:
    bitset<N> _bs1;
    bitset<N> _bs2;
  };

【4】给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件的交集?

  • 分析:
  • 第一种思路是:把其中一个文件存入位图,遍历另一个文件元素,将问题转变成"在不在"问题
  • 问题缺陷: 这种问题存在去重问题,即多次重复(下图中,交集明明只有一个3,但是会出现多个重复的3交集)
  • 分析:
  • 第二种思路是:将两个文件映射到两个位图中去(实现去重)
  • 如果相对应的位置都是1(满足相&为1),则此元素就在交集中


相关文章
|
5天前
|
存储 数据采集 数据处理
【数据结构进阶】位图
位图是一种高效的数据结构,通过二进制的0和1表示数据的存在状态,适用于海量数据的压缩存储与快速检索。本文从概念、实现到应用场景全面解析位图。核心思想是将数据映射到位图的比特位,利用位运算实现O(1)时间复杂度的增删查操作。文章通过C++代码示例展示了位图的三大接口(set、unset、test)实现,并对比自定义位图与标准库`bitset`的异同。位图优点在于极高的时间和空间效率,但仅适用于整型数据。它为布隆过滤器等高级结构奠定了基础,在数据处理领域具有重要价值。
36 1
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
97 29
|
1月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
1月前
|
存储 机器学习/深度学习 人工智能
C 408—《数据结构》易错考点200题(含解析)
408考研——《数据结构》精选易错考点200题(含解析)。
161 27
|
4月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
117 5
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
112 1
|
4月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
91 5
|
4月前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
4月前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
14天前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
65 29

推荐镜像

更多