Bit-map算法

来源:互联网 发布:mac在线恢复加速2017 编辑:程序博客网 时间:2024/06/02 01:48

ref: 

http://www.cnblogs.com/fanqs/archive/2012/12/07/bitmap.html

http://blog.csdn.net/sprayabc/article/details/7854672

http://www.cnblogs.com/huangxincheng/archive/2012/12/06/2804756.html

今天看到了一个新的算法,折腾了一会儿,稍微明白了一点东西,留个笔记

-------------------------------------------------------------------------------------

     在普通的32位机器上,一个整形,在内存中占用了 32 bit 位的空间。我们可以利用这 32 bit 位分别代表 0-31 这些数字, bitmap 就是利用这种思想进行处理大量数据的排序和查找。

     优点:1.运算效率高,不许进行比较和移位;2.占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M。 
      缺点:所有的数据不能重复。即不可对重复的数据进行排序和查找。 

     比如:  2                           00000000000000000000000000000100

             再添加一个4的时候变为    00000000000000000000000000010100

             再添加一个1的时候变为    00000000000000000000000000010110    ( 数字1,2,4时a[0]的位情况,这样a【0】一个int型就能保存0到31个数字了

    这个算法的中心就是将数字映射到与之相对应的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数组的具体位置

#include <iostream>
#include <random>
#include <time.h>
using namespace std;

#include <stdio.h> 
#define BITSPERWORD 32 
#define SHIFT 5 
#define MASK 0x1F 
#define N 10000000

int a[1 + N/BITSPERWORD];//申请内存的大小

//set 设置所在的bit位为1 
//clr 把i对应的位清为0 这样i从0到31把a[0]清0,i从32到63把a[1]清0,依次类推
//test 测试所在的bit为是否为1

void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } 
void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } 
int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); }

int main()

int i = 0;
int len = 1 + N/BITSPERWORD;
srand(time(0));

for( int j = 0; j < len; j++ )
{
a[j] = rand();
}

for (i = 0; i < len*32; i++) // i从0到31把a[0]清0,i从32到63把a[1]清0,依次类推,最终把a数组元素全部清0 
{
clr(i); 
}

for( i = 0; i < len; i++ ) // 用clr最终也是要把a数组清0,还不如直接赋值为0
{
a[i] = 0;
}


for( int j = 0; j < len; j++ )
{
cout << a[j] << " ";
}

 

while (scanf("%d", &i) != EOF) 
{
set(i); 
}

for (i = 0; i < len*32; i++)  // 数组a中能表示的最大数为len*32-1
{
if ( test(i) )
{
printf("%d\n", i); 
}

}

system("pause");
return 0; 
}

如上代码所示:

 

           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)   (把1左移)

         在 32 bit 中,将i所在bit位设为1。 得到 如: 0000000000000010000000000000000 的二进制数字

          a[i>>SHIFT] |= (1<<(i & MASK))

         将要改变数字 与 项对应的数字取或运算 即可将所需要添加的数字 添加到数组中去,完成一个添加过程。

 

0 0
原创粉丝点击