📖1. 位图概念
在讲解位图之前,我们先来看一道题:
给40亿个不重复的无符号整数,没排过序. 给一个无符号整数,如何快速判断一个数是否在这40亿个数中?
那我们第一时间就可以想到:
1、遍历这40亿个整数,看这个数在不在
但是40亿个整数,假设在32位机器下,40亿整数所占空间为16G
,而内存只有4G
,所以我们不可能一次性将它加载进内存,所以只能将这些数据分批加载,比如一次加载2G
,加载8次,然后每加载一次都进行查找.在这个过程中,我们需要8次从磁盘将数据加载进内存,这是IO操作,所以会非常慢,而且遍历查找时间复杂度O(N)
,所以这并不可行.
2、将数据加载到set/unordered_set
,然后通过它们的接口进行查找,但是,我们仔细分析一下:
3、先对文件中的数据进行外排序,再进行二分查找
由于文件中的数据不支持随机访问,所以也不可行
所以,我们需要用位图来解决这个问题:
数据是否在给定的数据中,结果是在或不在,刚好是两种状态,那么就可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表为存在,为0则代表不存在.
📖2. 位图的实现
位图整体代码:
#pragma once
#include<vector>
using namespace std;
template<size_t N>
class BitSet
{
public:
BitSet()
{
_bitTable.resize(N / 8 + 1);
}
void set(size_t x)
{
int pos = x / 8;
int j = x % 8;
_bitTable[pos] |= (1 << j);
}
void reset(size_t x)
{
int pos = x / 8;
int j = x % 8;
_bitTable[pos] &= (~(1 << j));
}
bool test(size_t x)
{
int pos = x / 8;
int j = x % 8;
return _bitTable[pos] &= (1 << j);
}
private:
vector<char> _bitTable;
};
📖3. 位图的应用
位图的应用:
- 快速查找某个数据是否在一个集合中
- 排序+去重
- 求两个集合的交集、并集等
- 操作系统中磁盘块标记