使用位图bitmap记录数的出现情况
位图
用途
节省空间,一般用于统计数据是否出现过,在网络编程中select函数就是用位图记录IO事件的。
传统我们记录数据就是以桶或者哈希的思想,确实高效,但是某些情况下,这些手段在位图面前还是小巫见大巫了。
模拟场景
假设现在给你一组数,范围在[0 ~ 99]之间,我们如何记录哪些数出现过?(不考虑出现次数)
解:一种可行的方案是使用哈希思想,创建一个数组,利用下标来记录这些数,因为数的范围在 0 ~ 99 , 因此可以创建一个 100 * sizeof(char) 大小的数组,但是这样也用了100Byte大小的空间,有什么更好的方法吗?
使用位图的思想,每一个int类型的数据为4Byte大小,也就是 8 * 4 = 32 bit, 借助每一位的01情况可以表示该数是否出现过。
例如现在给一个数 i = 13;
那么 i / 32 = 0 表示数字 i 应该用第一个int数来表示,
i % 32 = 13表示这个数 i 用第一个数中的第13位(从左往右数)表示
代码示例
#include <iostream>
#include <vector>
using namespace std;
int main() {
int* arr = new int[4]{ 0 };
//arr[0] 用于记录 0 ~ 31 arr[1] 记录 32 ~ 63 arr[2] 记录 64 ~ 95
//存储0 ~ 99只需要4个int单元就可以了
//现给出一段数据,使用位图记录他们的出现情况
vector<int> vec{ 2,3,6,44,74,13 };
for (auto& e : vec) {
int i = e / 32;//找出对应存放于哪个int单元
int j = e % 32;//对应的偏移地址
arr[i] = arr[i] | (1 << (31 - j));//进行位或运算
}
for (int i = 0; i < 4; i++) {
//找出出现过的数
for (int j = 31; j >= 0; j--) {
if ((arr[i] >> j) & 1) {
cout << (i * 32 + 31 - j) << " ";
}
}
}
}

浙公网安备 33010602011771号