趣味数据结构 – BitMap

1、什么是Bit-Map

Bit-Map被译为位图,和人讨论的时候,常常会与.BMP搞混,这个Map我觉得翻译成映射更为合适,Bit-Map也算是Hash的一直极致运用吧。Bit-Map会用Bit来标记某个元素对应的value,如何标记的呢,见下例:

我们现在有(1,2,5,8,10)数组,常规来说是这样声明的:

int[] array = {1, 2, 5, 8, 10}

上面这样声明会占用4×5个字节,即20个字节,少量数据可能没有什么特别大的感觉,如果数组长度为10,000,000,这样的方式就会占用4G的内存。

如果用Bit-Map的话,可以这样来组织:

byte[] bytes = new bytes[2];

bytes[0] = 01100100; // 就直接写二进制了

bytes[1] = 10100000;

2、Bit-Map建立

有了上面的例子之后,不知道对Bit-Map是否有了一个感性的认识。下面说下Bit-Map的建立过程。

1)开辟定长数组

Bit-Map会声明一个定长的byte/int数组,之后将数组内元素的所有Bit位均置为0,如下图:

image

2)遍历数据,并插入Bit-Map

上例来说,就会遍历array{1, 2, 5, 8, 10},并将所有的元素均插入Bit-Map中。Bit-Map是Hash的极致,那么key即为array[i]/8,value即在byte中的位置array[i]%8。而实际中为了效率,hash函数可能会有些出入。如下:

Byte: MASK = 0X07; SHIFT = 3; Integer: MASK = 0X1F; SHIFT = 5;

// i>> SHIFT => i/8; i & MASK => i%8

set(i): array[i>>SHITF] |= (1 << (i & MASK);

// return 0: not exist

isExist(i) : return array[i>>SHIFT] & (1 << (i & MASK);

遍历插入之后的数据应该是这样的:

image

3、Bit-Map应用

建立了Bit-Map之后,就可以方便的使用了。一般来说Bit-Map可作为数据的查找、去重、排序等操作。

如上面提及的10,000,000个数据存储问题,用Integer存储,耗费4G内存。改成Bit-Map,耗费125MB内存。但是实际中,可能由于数据中最大最小值相差太大,如{1,2 99999},只有三个数,但是最大最小相差悬殊,该方法就不适用了。

查找和去重都好理解,至于排序,有点类似桶排序,每个byte都是一个桶。至于应用实例,自个用的少,copy别人的吧。

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

8位最多99 999 999,大概需要99m个bit,大概10几m字节的内存即可。可以理解为从0-99 999 999的数字,每个数字对应一个Bit位,所以只需要99M个Bit==1.2MBytes,这样,就用了小小的1.2M左右的内存表示了所有的8位数的电话。

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

将bit-map扩展一下,用2bit表示一个数即可:0表示未出现;1表示出现一次;2表示出现2次及以上,即重复,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。或者我们不用2bit来进行表示,我们用两个bit-map即可模拟实现这个2bit-map,都是一样的道理。

参考资料:

码农:海量数据处理专题(四)——Bit-map


来源:http://www.wikieno.com/2012/03/data-structure-bitmap/


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值