bitmap算法

问题:

     一台主机,2G内存,40亿个不重复的没排过序的unsigned int的整数的文件,然后再给一个整数,如何快速判断这个整数是否在那40亿个数当中?

解决法案:


遍历法

     如果内存足够将40亿个数全部放到内存中,逐个遍历,此时时间复杂度为O(N).可是现在在内存不足,需要批量读一部分数据到内存然后在做判断,加上I/O操作的时间,时间复杂度远远大于O(N).
     这时,性能问题主要集中在I/O操作,和遍历数组上。那么有没有降低时间复杂度的方法呢?答案是肯定的,如果我们假定内存是足够的,只去优化时间,可以得到下面的方法。

直接寻址表法

    申请一个4G超大数组char a[0~2*32-1],将文件中出现的数字置为1,没有出现的置为0.
例如文件存在一个整数1000022,就将a[1000022]=1.
    
a 0 1 2 ...... 1000022 ..... 100000030 ... 2*32- 1 
flag 0 1 1 1 0 0 1 0 1
    这时时间复杂度为O(1),可是空间问题还没有解决。分析下我们的算法,以所需判断的整数为数组下标,用0/1来区分整数是否在。一共用了一个字节来作为标记位,而事实上1-bit就足够标记了。如果能把这部分空间优化掉,4G/8 < 2G 那么就可以解决问题了。看下面的方法。

Bit-Map

    将整数映射到bit上,例如整数10,10/8=1,10%8=2,那么就将a[1]的b[2]置为1。这样时间复杂度即是O(1),内存也得到了压缩。
a 0 1 ...... 2*32 / 8- 1 
bit 0 1 2 3 4 5 6 7  0 1 2 3 4 5 6 7  ...... 0 1 2 3 4 5 6 7 
flag 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ...... 0 0 0 0 0 0 0 0


BitMap 实现

  1. <span style="font-family:Microsoft YaHei;font-size:14px;">#define WORD 8  
  2. #define SHIFT 3 移动5个位,左移则相当于乘以8,右移相当于除以8取整    
  3. #define MASK 0x07   
  4. #define N 100000000    
  5. char bitmap[1 + N / WORD];    
  6. /*  
  7.  * 置位函数——用"|"操作符,i&MASK相当于mod操作  
  8.  * m mod n 运算,当n = 2的X次幂的时候,m mod n = m&(n-1)  
  9.  */    
  10. void set(int i) {    
  11.     bitmap[i >> SHIFT] |= (1 << (i & MASK));    
  12. }    
  13. /* 清除位操作,用&~操作符 */    
  14. void clear(int i) {    
  15.     bitmap[i >> SHIFT] &= ~(1 << (i & MASK));    
  16. }    
  17. /* 测试位操作用&操作符 */    
  18. int test(int i) {    
  19.     return bitmap[i >> SHIFT] & (1 << (i & MASK));    
  20. }  </span>  

BitMap 应用

枚举

1.全组合

     字符串全组合枚举(对于长度为n的字符串,组合方式有2^n种),如:abcdef,可以构造一个从字符串到二进制的映射关系,通过枚举二进制来进行全排序。

     null --> 000000

     f --> 000001

     e -->  000010

     ef --> 000011

     ……

     abcedf --> 111111

2.哈米尔顿距离

给定N(1<=N<=100000)个五维的点A(x1,x2,x3,x4,x5),求两个点X(x1,x2,x3,x4,x5)和Y(y1,y2,y3,y4,y5),使得他们的哈密顿距离(d=|x1-y1| + |x2-y2| + |x3-y3| + |x4-y4| + |x5-y5|)最大。

搜索

     爬虫系统中常用的URL去重(Bloom Filter算法)

压缩

     在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数?

     给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

     位排序


转载自: http://blog.csdn.NET/liufei_learning/article/details/19303179

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值