对于自然数序列,如果序列元素范围比较集中,那么位图法是一个巧妙的实现诸如排序和检索之类的工作的方法,再配合位逻辑运算的话,可以在时间和空间效率上都达到较好的水平。我们为了实现这个方法,首先构造一个位向量,然后通过定义以下三个基本的函数,再以序列元素值取操纵这些函数,从而完成所需功能。
#define SHIFT 3
#define BMASK 0x7
const int n = 1000;
unsigned char map[n/8 + 1];
void set(const int i)
{
map[i >> SHIFT] |= 1 << (i & BMASK);
}
void clear(const int i)
{
map[i >> SHIFT] &= ~(1 << (i & BMASK));
}
bool test(const int i)
{
return map[i >> SHIFT] & (1 << (i & BMASK));
}
值得注意的是右移操作,在有些平台中,如果右移操作的实现是在左端补1,上面的函数将有错误!至于哪些平台补0,哪些补1,额,我也知道得不具体。。。
当然,位图法是巧妙的,但也知识众多奇妙技巧中的一员而已,对于C++,标准模板库中的bitset的功能已完全覆盖我们上面所作的工作。所以,更多的恐怕是要去探索更好更简洁的思路,正如Jon Bentley在《编程珠玑》中所表明的意思:与其花1分钟时间思考,然后花一天的时间来写代码(PS: 话说,对我等菜鸟来讲,写代码也是一种极力的思考啊!思想的考验啊!智商的考验啊!),不如先花1个钟头来思考,再用一个钟头来实现。