bitmap学习

第一次见到bitmap这个数据结构是在《编程珠玑》这本书中,当时第一感觉这个数据结构真的好强大,能够这么巧妙的处理海量数据的处理。接下来我们来简单学习一下这个强大的工具。

bitmap是查找算法中常用到的一种算法,通过该数据结构,我们能够很快的判断某一个元素是否在某一个集合中。(当然我们需要提前把该集合利用bitmap算法把集合存储起来)。bitmap的思路其实和hash,索引排序的思路是相似的。

我们无非都是在寻找一种如何快速得到存储元素的下标(存储地址)的方法而已。而hash的做法是将每一个元素通过一个函数映射到一个下标索引(建立元素和地址的映射关系),而bitmap的做法是花费最小的存储单元(bit)来说明某一个元素是否存在,而地址则是该bit从第0位开始的位数(该位的表示有两个含义:该元素值的大小,该元素是否存在)。举个例子:如果我们需要对0-7内的5个元素(4,7,2,5,3)进行排序,我们我们可以使用bit-map的方法来达到排序的目的。要表示8个数,我们需要8个bit(1字节),首先开辟1字节的空间,将这些空间的所有bit位都初始化为0,如下所示:

接着我们就开始遍历每一个待排序的元素,首先是第一个元素4,那么就把刚才开辟的空间的第4位置为1。。。。等我们把所有的元素遍历完之后,bitmap结构就建立好了。结果如下所示:

接下来我们就可以利用该结构干我们需要做的事情了,比如输出该序列的有序序列(结果就是排序后的结果),查询某一个元素是否在该集合之中,查询该集合中有多少个不同的元素等等。(注:bitmap的排序功能和桶排序有一样的限制---待排序元素为不重复的)

下面是一个很经典的bitmap排序程序

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1+N/BITSPERWORD];

void set(int i) { a[i>>SHIFT] |= (1 << (i & MASK));}
void clr(int i) { a[i>>SHIFT] &= ~(1 << (i & MASK));}
int test(int i) { return a[i>>SHIFT] & (1<<(i & MASK));}

int main(){
	int i;
	for(i=0;i<N;i++) clr(i);
	while(scanf("%d",&i)!=EOF) set(i);
	for(i=0;i<N;i++) 
		if(test(i)) printf("%d\n",i);
	return 0;
}

这里使用了int数组作为bitmap的存储空间,所以在对待存储数字的使用了稍微复杂一点的移位操作。

总结:bitmap数据结构的主要功能是实现快速查询某一元素是否存在于某一个集合当中。当然了我感觉它只能用来处理数字集合问题,而对于其它的非数字问题则显得力不从心。

问题实例:

1 已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数 

  看到这个问题之后,我们很多人都会想到用一个数组去存储所有这些元素,然后遍历所有的元素统计不同号码的个数,对,但你有没有想到过索引,想到过bitmap做这件事情其实更高效呢?分析一下8位数字能够表示的最大数字99999999,我们分配一个99999999bit大小的空间(比你使用索引的方法节省了好多的空间),接着遍历每一个电话号码。因为题目要的是结果是不同的号码数目,并不要求每个号码有多少次出现,所以遍历到一个号码的时候,就将该号码位置为1,比如遇到12345678,那么我们就将第12345678位置为1。这样在所有的元素遍历完之后,就得到了一个很大0,1组合序列。这个时候我们就很容易得到答案了(就是该序列中到底有多少个1),至于怎么得到这个1个数的高效算法,你知道吗?呵呵。

2 2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。  

  不重复的个数,有的人会想,如果像用问题1 一样用bitmap解决这个问题的话,好像有问题,因为bitmap能够解决的问题只是判断某一个元素是否存在于一个集合之中,而现在需要判断的是某一个元素是否重复,对我们来讲,需要判断的某一个元素的状态一共有3种,不存在,存在,重复。我们知道如果需要表示3种状态需要的最小空间为2bit,对了,我们可以变通一下原来的bitmap算法嘛。用两位来表达一个元素,当遇到一个元素的时候将连续两位置为01,后面再次遇到该元素的话就将该元素置为10.以后再遇到就不变了,所以遍历完所有元素之后,再来看这个问题是不是就很简单了?

注:实例部分参考http://blog.csdn.net/v_JULY_v

posted @ 2012-06-27 20:33  f_x_p  阅读(835)  评论(0编辑  收藏  举报