欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

BitMap算法详解

程序员文章站 2022-03-14 14:56:32
BitMap算法详解 原文链接:https://www.cnblogs.com/senlinyang/p/7885685.html 所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间。 基本思想 ......

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

基本思想:

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

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

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

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

  BitMap算法详解

  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]中的下标

代码实现:

 1 public class bitmap {
 2 
 3     private static final int n = 10000000;
 4 
 5     private int[] a = new int[n/32 + 1];
 6 
 7     /**
 8      * 设置所在的bit位为1
 9      * @param n
10      */
11     public void addvalue(int n){
12         //row = n / 32 求十进制数在数组a中的下标
13         int row = n >> 5;
14         //相当于 n % 32 求十进制数在数组a[i]中的下标
15         a[row] |= 1 << (n & 0x1f);
16     }
17 
18     // 判断所在的bit为是否为1
19     public boolean exits(int n){
20         int row = n >> 5;
21         return (a[row] & ( 1 << (n & 0x1f))) != 1;
22     }
23 
24     public void display(int row){
25         system.out.println("bitmap位图展示");
26         for(int i=0;i<row;i++){
27             list<integer> list = new arraylist<integer>();
28             int temp = a[i];
29             for(int j=0;j<32;j++){
30                 list.add(temp & 1);
31                 temp >>= 1;
32             }
33             system.out.println("a["+i+"]" + list);
34         }
35     }
36 
37     public static void main(string[] args){
38         int num[] = {1,5,30,32,64,56,159,120,21,17,35,45};
39         bitmap map = new bitmap();
40         for(int i=0;i<num.length;i++){
41             map.addvalue(num[i]);
42         }
43 
44         int temp = 120;
45         if(map.exits(temp)){
46             system.out.println("temp:" + temp + "has already exists");
47         }
48         map.display(5);
49     }
50 }

应用范围:
  可以运用在快速查找、去重、排序、压缩数据等。