海量数据---位图法的应用

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

申请512M的内存(40亿 < 2^32 = 8*2^29 bit = 2^9M bytes = 512M
一个bit位代表一个unsigned int值
读入40亿个数,设置相应的bit位
读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在

 

二、使用位图法判断整形数组是否存在重复

判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。

位图法比 较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N(扫描两次,第一次找最大值,第二次位图赋值判断重复)。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。

 

三、使用位图法进行整形数组排序

找到最小值和最大值,申请位图数组,对应位赋值为1,最后依次输出。

 

四、位图法存数据

在 8K 字节的内存空间内,如何存 unsigned short 类型数据?

一般做法:

定义一个数组: 

unsigned short arrNormal[4096];

这样做,最多只能存 4K 个 unsigned short 数据。

 
利用位图法:

定义一个数组:

unsigned char arrBit[8192];


这样做,能存 8K*8=64K 个 unsigned short 数据。(每一个bit表示1个数字)
 
写数据元素:计算待写入数据在 arrBit 存放的字节位置和位位置(字节 0~8191,位 0~7 )

比如写 1234 ,字节序: 1234/8 = 154; 位序: 1234 & 0b111 = 2 ,那么 1234放在 arrBit 的下标 154 字节处,把该字节的 2 号位( 0~7 )置为 1
 
字节位置:

int nBytePos = 1234/8 = 154;

位位置: 

int nBitPos = 1234 & 7 = 2;

把数组的 154 字节的 2 位置为 1

1 unsigned short val = 1<<nBitPos;
2 arrBit[nBytePos] = arrBit[nBytePos] | val;  // 写入 1234 得到
3 arrBit[154]=0b00000100

此时再写入 1236 ,

字节位置:

int nBytePos = 1236/8 = 154;

位位置:  

int nBitPos = 1236 & 7 = 4

把数组的 154 字节的 4 位置为 1

1 val = 1<<nBitPos;
2 arrBit[nBytePos] = arrBit[nBytePos] | val;  // 再写入 1236 得到
3 arrBit[154]=0b00010100

读数据元素:按位读取 arrBit ,取得位为 1 的字节位置和位位置。元素值为 8*nBytePos + nBitPos

 1 for (i=0; i<8192; i++)
 2 {
 3        for (j=0; j<8; j++)
 4        {
 5               if (arrBit[i] & (1<<j))
 6               {
 7                      cout << "arrBit:" << i << " " << j << "     " << 8*i+j << endl;
 8               }
 9        }
10 }

会输出:

1 arrBit:154 2     1234
2 arrBit:154 4     1236


*删除元素:计算待删除元素的字节位置和位位置:

arrBit[nBytePos] &= ~(1<<nBitPos); 

比如删除 1234 : 

arrBit[154] &= ~(1<<2);


*位图法的缺点:

  1. 可读性差
  2. 位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。

*位图存储性质:存储的元素个数等于元素的最大值。
*比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为8K ,这个局限性很大!)
*比如,要存储值为 65535 的数,就必须要 65535/8=8K 字节的内存。要就导致了位图法根本不适合存 unsigned int 类型的数(大约需要 2^32/8=5 亿字节的内存)。

3. 位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。
*比如 8K 字节内存空间存储 short 类型数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K 。

综上所诉:位图法的适用范围很特殊。


http://www.360doc.com/content/11/0528/20/2660674_120142707.shtml

posted @ 2012-07-01 15:18  wolenski  阅读(822)  评论(0编辑  收藏  举报