使用位图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) << " ";
			}
		}
	}
}
posted @ 2021-07-28 22:39  nepu_bin  阅读(105)  评论(0)    收藏  举报