位图的概念
位图的本质其实就是直接定值法的哈希,就是用每一个比特位来存放某种状态(通常用来表示该元素是否存在),由于表示每一个数据是否存在只需要使用一个比特位,其优点是节省空间,适用于海量数据,数据无重复的场景。
namespace ZJ
{
template<size_t N>
class BitSet
{
public:
BitSet();
void set(const size_t& val);
void reset(const size_t& val);取消位
bool test(const size_t& val)const;
public:
std::vector<int> _bits;
};
}
位图的实现
构造函数
在我们使用位图时,首先要做的第一件事就是根据所需要N位数来创建N位的位图,并将所有的位图的所有位置都设置为0(即每一个位上表示的数据不存在)。 但是一个整形是有32个比特位的,因此用户输入N个位的位图就需要用到N/32个整形,但是实际我们所需要的整形个数是N/32+1,因为用户输入的位数可能小于1个整形所含盖的位数。 例如:当用户输入的位数是48位时,此时我们就需要创建两个整形(int),即需要 48 / 32 + 1 = 2,共计64个比特位。
BitSet()
{
_bits.resize(N / 32 + 1, 0);
}
set
set函数用于将某个值所映射的位置设置为存在状态,即对应的比特位设置为1。
设置x值对应到位图中指定的位的方法如下:
- 计算出该数(x)位于第 i 个整数的第 j 个比特位。
- 将1左移 j 位后与第 i 个整数进行或运算即可。
具体如下图所示:
void set(size_t x)
{
assert(x < N);
size_t i = x / 32;
size_t j = x % 32;
_bits[i] |= (1 << j);
}
reset
set函数用于将某个值所映射的比特置为不存在状态,即置为0。
清空x值对应到位图中指定的位的方法如下:
- 计算出该值对应位图当中第 i 个整数的第 j 个比特位。
- 将1左移 j 位再取反后与第 i 个整数进行与运算即可。
具体如下图所示:
void reset(size_t x)
{
assert(x < N);
size_t i = x / 32;
size_t j = x % 32;
_bits[i] &= (~(1 << j));
}
test
tes函数用于获取x值对应的比特位的数据是否存在。
获取位图中x值对应指定的位的状态的方法如下:
- 计算出该位位于第 i 个整数的第 j 个比特位。
- 将1左移 j 位后与第 i 个整数进行与运算得出结果。
- 若结果非0,则该位对应的数据存在,否则该不存在。
bool test(size_t x)
{
assert(x < N);
size_t i = x / 32;
size_t j = x % 32;
return _bits[i] & (1 << j);
}
下期预告:C++11!!!
|