位图
-
先来一个面试题刺激一下神经
-
给40亿个不重复的无符号整数,没排过序.给一个无符号整数,如何判断一个数是否在这40亿个数中
40亿个不重复的无符号整数中查找一个确定一个数的存在与否,这是登天的难度? -
解决办法
- 1.遍历,时间复杂度O(N)
- 2.排序(O(NlogN)),利用二分查找:logN
- 3.位图来解决
数据是否在给定的整形数据中,在或者不在(刚好是两种状态),那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在,
位图概念
-
所谓位图,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况.通常是用来判断某个数据存在不存在的.
-
例如:在32位平台下,一个整数占用4个字节既一共占用32个比特位,可以表示32个数据存在与否的状态.
-
比如,我们要标记1000个数据(这些数据都是小于等于1000的)的存在状态,1000/32大约是31.则需要申请32个整形就可以标识1000个整数的存在状态.
个人理解就是通过比特位的移动和补充来记录元素的存在与否的状态
位图的模拟实现
#include<vector>
#include<iostream>
using namespace std;
class bitSet{
public:
bitSet(size_t range)
:_bits()
{
_bits.resize((range>>5)+1);
}
//把X对应的为设置为1,表示存在
void Set(size_t X){
size_t index=X>>5;
size_t bitNum=X%32;
_bits[index] |=(1<<bitNum);
}
void ReSet(size_t X){
size_t index=X>>5;
size_t bitNum=X%32;
_bits[index] &=(~(1<<bitNum) );
}
//检查X对应的位是否位1
bool TestBSet(size_t X){
size_t index=X>>5;
size_t bitNum=X%32;
return _bits[index]&(1<<bitNum);
}
private:
vector<int> _bits;
};
- 测试结果
位图中"存入"数据的过程分析
- 说明:resize()之后的内存中数据默认设置为0
void Set(size_t X){
size_t index=X>>5;
size_t bitNum=X%32;
_bits[index] |=(1<<bitNum);
}
- 如图
从位图中"清除"某个数据的存储状态过程分析
- 假设原状态只表示5的存在状态
void ReSet(size_t X){
size_t index=X>>5;
size_t bitNum=X%32;
_bits[index] &=(~(1<<bitNum) );
}
- 图示
位图的应用
- 1.快速查找某个数据是否在一个集合中
- 2.排序
- 3.求连个集合的交集、并集等
- 4.操作系统中磁盘块标记