bitmap 算法
今天看到了一个新的算法,折腾了一会儿,稍微明白了一点东西,留个笔记
-------------------------------------------------------------------------------------
在普通的32位机器上,一个整形,在内存中占用了 32 bit 位的空间。我们可以利用这 32 bit 位分别代表 0-31 这些数字, bitmap 就是利用这种思想进行处理大量数据的排序和查找。
优点:1.运算效率高,不许进行比较和移位;2.占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M。
缺点:所有的数据不能重复。即不可对重复的数据进行排序和查找。
比如: 2 00000000000000000000000000000100
再加一个4的时候变为 00000000000000000000000000010100
再加一个1的时候变为 00000000000000000000000000010110
这个算法的中心就是将数字映射到与之相对应的bit位上即可。
假设需要排序或查找的数字最大数为 N = 1000000 (总数在N以内即可),则需要申请空间为 int a[1 + N/32] 即可。
因此 bitmap 表为:
a[0]--------->0-31
a[1]--------->32-63
a[2]--------->64-95
a[3]--------->96-127
..........
对于此算法中主要两个算法就是:
1、获取数字 i 所在对应数组索引
2、获取数字 i 所在bit数组的具体位置
1 #include <stdio.h> 2 3 #define BITSPERWORD 32 4 #define SHIFT 5 5 #define MASK 0x1F 6 #define N 10000000 7 8 int a[1 + N/BITSPERWORD];//申请内存的大小 9 10 //set 设置所在的bit位为1 11 //clr 初始化所有的bit位为0 12 //test 测试所在的bit为是否为1 13 14 void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } 15 void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } 16 int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); } 17 18 int main() 19 { int i; 20 for (i = 0; i < N; i++) 21 clr(i); 22 while (scanf("%d", &i) != EOF) 23 set(i); 24 for (i = 0; i < N; i++) 25 if (test(i)) 26 printf("%d\n", i); 27 28 return 0; 29 }
如上代码所示:
i >> SHIFT
我们所用数字保存在32 bit位的内存中,因此 i >> SHIFT 就相当于 i / 2^5 即 i / 32 得到 i 所保存在的对应数组的索引。
i & MASK
MASK = 0x1F 就是31 换做二进制就是 11111 与 i 取 与运算 得到 i 二进制的后5位 也就是相当于 i 与 32 取余 即 i%32 。此时得到的就是 i 在相应的bit数组中所在的具体位置了。
1 << (i & MASK)
在 32 bit 中,将i所在bit位设为1。 得到 如: 0000000000000010000000000000000 的二进制数字
a[i>>SHIFT] |= (1<<(i & MASK))
将要改变数字 与 项对应的数字取或运算 即可将所需要添加的数字 添加到数组中去,完成一个添加过程。
参考链接:
http://blog.csdn.net/fanshadoop/article/details/7854672
http://www.cnblogs.com/huangxincheng/archive/2012/12/06/2804756.html

浙公网安备 33010602011771号