所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间。

一、Bit-map的基本思想
  32位机器上,对于一个整型数,比如int a=1 在内存中占32bit位,这是为了方便计算机的运算。但是对于某些应用场景而言,这属于一种巨大的浪费,因为我们可以用对应的32bit位对应存储十进制的0-31个数,而这就是Bit-map的基本思想。Bit-map算法利用这种思想处理大量数据的排序、查询以及去重。Bitmap在用户群做交集和并集运算的时候也有极大的便利。

在此我用一个简单的例子来详细介绍BitMap算法的原理。假设我们要对0-7内的5个元素(4,7,2,5,3)进行排序(这里假设元素没有重复)。我们可以使用BitMap算法达到排序目的。要表示8个数,我们需要8个byte。

  1.首先我们开辟一个字节(8byte)的空间,将这些空间的所有的byte位都设置为0

  2.然后便利这5个元素,第一个元素是4,因为下边从0开始,因此我们把第五个字节的值设置为1

  3.然后再处理剩下的四个元素,最终8个字节的状态如下图

               

  4.现在我们遍历一次bytes区域,把值为1的byte的位置输出(2,3,4,5,7),这样便达到了排序的目的

  从上面的例子我们可以看出,BitMap算法的思想还是比较简单的,关键的问题是如何确定10进制的数到2进制的映射图

MAP映射:

  假设需要排序或则查找的数的总数N=100000000,BitMap中1bit代表一个数字,1个int = 4Bytes = 4*8bit = 32 bit,那么N个数需要N/32 int空间。所以我们需要申请内存空间的大小为int a[1 + N/32],其中:a[0]在内存中占32为可以对应十进制数0-31,依次类推:

  a[0]-----------------------------> 0-31

  a[1]------------------------------> 32-63

  a[2]-------------------------------> 64-95

  a[3]--------------------------------> 96-127

  ......................................................

  那么十进制数如何转换为对应的bit位,下面介绍用位移将十进制数转换为对应的bit位:

  1.求十进制数在对应数组a中的下标

  十进制数0-31,对应在数组a[0]中,32-63对应在数组a[1]中,64-95对应在数组a[2]中………,使用数学归纳分析得出结论:对于一个十进制数n,其在数组a中的下标为:a[n/32]

  2.求出十进制数在对应数a[i]中的下标

  例如十进制数1在a[0]的下标为1,十进制数31在a[0]中下标为31,十进制数32在a[1]中下标为0。 在十进制0-31就对应0-31,而32-63则对应也是0-31,即给定一个数n可以通过模32求得在对应数组a[i]中的下标。

  3.位移

  对于一个十进制数n,对应在数组a[n/32][n%32]中,但数组a毕竟不是一个二维数组,我们通过移位操作实现置1

  a[n/32] |= 1 << n % 32 
  移位操作: 
  a[n>>5] |= 1 << (n & 0x1F)

  n & 0x1F 保留n的后五位 相当于 n % 32 求十进制数在数组a[i]中的下标。

java代码实现:

public class BitMap {private static final int N = 10000000;private int[] a = new int[N/32 + 1];/*** 设置所在的bit位为1* @param n*/public void addValue(int n){//row = n / 32 求十进制数在数组a中的下标int row = n >> 5;//相当于 n % 32 求十进制数在数组a[i]中的下标a[row] |= 1 << (n & 0x1F);}// 判断所在的bit为是否为1public boolean exits(int n){int row = n >> 5;return (a[row] & ( 1 << (n & 0x1F))) != 0;}public void display(int row){System.out.println("BitMap位图展示");for(int i=0;i<row;i++){List<Integer> list = new ArrayList<Integer>();int temp = a[i];for(int j=0;j<32;j++){list.add(temp & 1);temp >>= 1;}System.out.println("a["+i+"]" + list);}}public static void main(String[] args){int num[] = {1,5,30,32,64,56,159,120,21,17,35,45};BitMap map = new BitMap();for(int i=0;i<num.length;i++){map.addValue(num[i]);}int temp = 120;if(map.exits(temp)){System.out.println("temp:" + temp + "has already exists");}map.display(5);}
}

运行结果:

temp:120has already exists
BitMap位图展示
a[0][0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
a[1][1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
a[2][1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
a[3][0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
a[4][0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

二、Bit-Map应用

1. Bit-map应用之快速去重
  2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。 
  首先,根据“内存空间不足以容纳这2.5亿个整数”我们可以快速的联想到Bit-map。下边关键的问题就是怎么设计我们的Bit-map来表示这2.5亿个数字的状态了。其实这个问题很简单,一个数字的状态只有三种,分别为不存在,只有一个,有重复。因此,我们只需要2bits就可以对一个数字的状态进行存储了,假设我们设定一个数字不存在为00,存在一次01,存在两次及其以上为11。那我们大概需要存储空间几十兆左右。
  接下来的任务就是遍历一次这2.5亿个数字,如果对应的状态位为00,则将其变为01;如果对应的状态位为01,则将其变为11;如果为11,,对应的转态位保持不变。
  最后,我们将状态位为01的进行统计,就得到了不重复的数字个数,时间复杂度为O(n)。

2. Bit-map应用之快速查询
  同样,我们利用Bit-map也可以进行快速查询,这种情况下对于一个数字只需要一个bit位就可以了,0表示不存在,1表示存在。假设上述的题目改为,如何快速判断一个数字是够存在于上述的2.5亿个数字集合中。
  同之前一样,首先我们先对所有的数字进行一次遍历,然后将相应的转态位改为1。遍历完以后就是查询,由于我们的Bit-map采取的是连续存储(整型数组形式,一个数组元素对应32bits),我们实际上是采用了一种分桶的思想。一个数组元素可以存储32个状态位,那将待查询的数字除以32,定位到对应的数组元素(桶),然后再求余(%32),就可以定位到相应的状态位。如果为1,则代表改数字存在;否则,该数字不存在。

三、总结

使用Bit-map的思想,我们可以将存储空间进行压缩,而且可以对数字进行快速排序、去重和查询的操作。适用范围:可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下。

参考文章:1、http://www.cnblogs.com/senlinyang/p/7885685.html

2、https://www.cnblogs.com/yangjiannr/p/da-shu-ju-chu-libitmap.html

【算法】——Bit-Map(位图)相关推荐

  1. 【数据结构与算法】7.位图算法、12306抢票算法

    前言 本文收录于专辑:http://dwz.win/HjK,点击解锁更多数据结构与算法的知识. 你好,我是彤哥,一个每天爬二十六层楼还不忘读源码的硬核男人. 相信大家都有过抢票.刷票的经验,每年年底, ...

  2. 【数据结构与算法】【算法思想】位图

    位图BitMap 算法 public class BitMap { // Java中char类型占16bit,也即是2个字节private char[] bytes;private int nbits ...

  3. 基于空间误差同质区的矢量电子地图快速纠偏算法 Fast Map Rectification Algorithm Based on Spatial Error Homogeneous Region...

    作 者:蔡文婷刘正坤 CAI Wen-tingLIU Zheng-kun(Dingxin Information Technology Co.Ltd,Guangzhou 510623Guangdong ...

  4. 算法之美——位图排序

    辉爷的高级数据结构开讲了,辉爷V5啊,今天辉爷讲的是位图排序. 问题描述: •输入 –给出至多10,000,000个正整数的序列 •特征: –每个数都小于10,000,000 –数据不重复且 数据之间 ...

  5. python【数据结构与算法】map() 映射函数(看不懂你来打我)

    文章目录 1 描述 2 语法 3 参数 4 返回值 5 实例 1 描述 map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函 ...

  6. JAVA 算法中Map 使用技巧,持续更新,边学边更

    1 在做一道必须统计出现次数的题目中,使用到了map函数 Map<Integer, Integer> count = new HashMap(); for (int i = 0; i &l ...

  7. 算法与数据结构——位图BitMap

    一.介绍 1.1 什么是位图 在Java中有四种整数类型:byte.short.int.long. 1 byte(字节) = 8 bit(位) 1 int = 4 byte = 32 bit 所以我们 ...

  8. 程序员求职成功路(2) - 第3章 数据结构与算法

    第3章 数据结构与算法 1. memmove边界问题 void memmove_(char *pDst,const char* pSrc,size_t size){     assert(pSrc!= ...

  9. 论文简述Reversible Data Hiding in Encrypted Images with Two-MSB Prediction加密图像可逆信息隐藏算法

    一 误差预测所用方法 1.中值预测器 使用中值预测器MED(Median Edge Detector),对图中x的左.上和左上三个相邻像素,预测出x的预测值px. 2.根据预测误差产生的位图(Loca ...

  10. CVPR目标检测与实例分割算法解析:FCOS(2019),Mask R-CNN(2019),PolarMask(2020)

    CVPR目标检测与实例分割算法解析:FCOS(2019),Mask R-CNN(2019),PolarMask(2020) 目标检测:FCOS(CVPR 2019) 目标检测算法FCOS(FCOS: ...

最新文章

  1. SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断
  2. 发送电子邮件模块smtplib
  3. 添加高精度计时器测量处理能力
  4. C++多线程实现电子词典
  5. Pyinstaller将Python程序打包成EXE(多种模式的打包)
  6. Redis与Memocache的区别
  7. C#委托的异步调用[转]
  8. 取多补少C语言,leetcode题目: 数字的补数 的C语言解法
  9. 创业 4 年获近 7000 万美元融资,53 岁老程序员 all in 开源
  10. 数据库-MySQL-搭建服务器
  11. (1)触发器systemverilog与VHDL编码
  12. 可口可乐开了家网店卖奶,价值62亿元
  13. keras提取模型中的某一层_Tensorflow笔记:高级封装——Keras
  14. Win10将中文用户名修改为英文
  15. 触摸屏下的MFC程序
  16. 【千律】C++基础:使用动态数组vector初始化自定义类
  17. 机器学习笔记六——特征工程之数据预处理
  18. 哈工大软件过程与工具复习5——第9讲 软件设计
  19. python抓取股票竞价数据_Python 抓取新浪财经股票数据
  20. 信号量机制中的down和up函数

热门文章

  1. java调用jce加密_关于加密:JCE无法在java swing应用程序中验证提供程序BC
  2. 21年-05-自研-自我准备
  3. OSChina 周三乱弹 —— 媳妇认真的思考了一下
  4. 版图设计Step1-交接表的阅读
  5. 【Go】如何正确理解error
  6. 转载深圳合租记经典台词
  7. 记一次在多哈的项目经历
  8. centos7安装thefuck命令
  9. MTK6765 COL0对地拉低开机慢问题
  10. 探索微前端的场景极限