Bootstrap

位图【概念 + C/C++实现】

📖1. 位图概念

在讲解位图之前,我们先来看一道题:

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

那我们第一时间就可以想到:

1、遍历这40亿个整数,看这个数在不在

但是40亿个整数,假设在32位机器下,40亿整数所占空间为16G,而内存只有4G,所以我们不可能一次性将它加载进内存,所以只能将这些数据分批加载,比如一次加载2G,加载8次,然后每加载一次都进行查找.在这个过程中,我们需要8次从磁盘将数据加载进内存,这是IO操作,所以会非常慢,而且遍历查找时间复杂度O(N),所以这并不可行.

2、将数据加载到set/unordered_set,然后通过它们的接口进行查找,但是,我们仔细分析一下:

image-20221028103638962

3、先对文件中的数据进行外排序,再进行二分查找

由于文件中的数据不支持随机访问,所以也不可行

所以,我们需要用位图来解决这个问题:

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

image-20221028202442454

📖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;
};

image-20221028210042597

📖3. 位图的应用

位图的应用:

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