海量数据处理算法—Bit-Map
1. Bit Map算法簡(jiǎn)介
? ? ? ?? 來自于《編程珠璣》。所謂的Bit-map就是用一個(gè)bit位來標(biāo)記某個(gè)元素對(duì)應(yīng)的Value, 而Key即是該元素。由于采用了Bit為單位來存儲(chǔ)數(shù)據(jù),因此在存儲(chǔ)空間方面,可以大大節(jié)省。
2、 Bit Map的基本思想
? ? ? ? 我們先來看一個(gè)具體的例子,假設(shè)我們要對(duì)0-7內(nèi)的5個(gè)元素(4,7,2,5,3)排序(這里假設(shè)這些元素沒有重復(fù))。那么我們就可以采用Bit-map的方法來達(dá)到排序的目的。要表示8個(gè)數(shù),我們就只需要8個(gè)Bit(1Bytes),首先我們開辟1Byte的空間,將這些空間的所有Bit位都置為0,如下圖:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
然后遍歷這5個(gè)元素,首先第一個(gè)元素是4,那么就把4對(duì)應(yīng)的位置為1(可以這樣操作 p+(i/8)|(0x01<<(i%8)) 當(dāng)然了這里的操作涉及到Big-ending和Little-ending的情況,這里默認(rèn)為Big-ending),因?yàn)槭菑牧汩_始的,所以要把第五位置為一(如下圖):
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
然后再處理第二個(gè)元素7,將第八位置為1,,接著再處理第三個(gè)元素,一直到最后處理完所有的元素,將相應(yīng)的位置為1,這時(shí)候的內(nèi)存的Bit位的狀態(tài)如下:?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
然后我們現(xiàn)在遍歷一遍Bit區(qū)域,將該位是一的位的編號(hào)輸出(2,3,4,5,7),這樣就達(dá)到了排序的目的。
優(yōu)點(diǎn):
1.運(yùn)算效率高,不許進(jìn)行比較和移位;
2.占用內(nèi)存少,比如N=10000000;只需占用內(nèi)存為N/8=1250000Byte=1.25M。?
缺點(diǎn):
? ? ? ?所有的數(shù)據(jù)不能重復(fù)。即不可對(duì)重復(fù)的數(shù)據(jù)進(jìn)行排序和查找。 ? ?
算法思想比較簡(jiǎn)單,但關(guān)鍵是如何確定十進(jìn)制的數(shù)映射到二進(jìn)制bit位的map圖。
3、 Map映射表
假設(shè)需要排序或者查找的總數(shù)N=10000000,那么我們需要申請(qǐng)內(nèi)存空間的大小為int a[1 + N/32],其中:a[0]在內(nèi)存中占32為可以對(duì)應(yīng)十進(jìn)制數(shù)0-31,依次類推:?bitmap表為:?
a[0]--------->0-31?
a[1]--------->32-63?
a[2]--------->64-95?
a[3]--------->96-127?
..........?
那么十進(jìn)制數(shù)如何轉(zhuǎn)換為對(duì)應(yīng)的bit位,下面介紹用位移將十進(jìn)制數(shù)轉(zhuǎn)換為對(duì)應(yīng)的bit位。?
3、 位移轉(zhuǎn)換?
申請(qǐng)一個(gè)int一維數(shù)組,那么可以當(dāng)作為列為32位的二維數(shù)組,
?????????????? |???????????????????????????32位??????????????????????? ? ? ? ? ? ? ?? |
int a[0]??? |0000000000000000000000000000000000000|
int a[1]??? |0000000000000000000000000000000000000|
………………
int a[N]?? |0000000000000000000000000000000000000|
例如十進(jìn)制0,對(duì)應(yīng)在a[0]所占的bit為中的第一位:?00000000000000000000000000000001?
0-31:對(duì)應(yīng)在a[0]中?
i =0 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000000?
temp=0 ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000000000?
answer=1 ? ? ? ? ? ? ? ? 00000000000000000000000000000001?
i =1 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000001?
temp=1 ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000000001?
answer=2 ? ? ? ? ? ? ? ? 00000000000000000000000000000010?
i =2 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000010?
temp=2 ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000000010?
answer=4 ? ? ? ? ? ? ? ? 00000000000000000000000000000100?
i =30 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000011110?
temp=30 ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000011110?
answer=1073741824??01000000000000000000000000000000?
i =31 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000011111?
temp=31 ? ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000011111?
answer=-2147483648?10000000000000000000000000000000?
32-63:對(duì)應(yīng)在a[1]中?
i =32 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000100000?
temp=0 ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000000?
answer=1 ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000001?
i =33 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000100001?
temp=1 ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000000001?
answer=2 ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000010?
i =34 ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000100010?
temp=2 ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000010?
answer=4 ? ? ? ? ? ? ? ? ? ?00000000000000000000000000000100?
i =61 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000111101?
temp=29 ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000011101?
answer=536870912?? ?00100000000000000000000000000000?
i =62 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000111110?
temp=30 ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000011110?
answer=1073741824??01000000000000000000000000000000?
i =63 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?00000000000000000000000000111111?
temp=31 ? ? ? ? ? ? ? ? ? ? ? ? 00000000000000000000000000011111?
answer=-2147483648??10000000000000000000000000000000
淺析上面的對(duì)應(yīng)表,分三步:?
1.求十進(jìn)制0-N對(duì)應(yīng)在數(shù)組a中的下標(biāo):?
十進(jìn)制0-31,對(duì)應(yīng)在a[0]中,先由十進(jìn)制數(shù)n轉(zhuǎn)換為與32的余可轉(zhuǎn)化為對(duì)應(yīng)在數(shù)組a中的下標(biāo)。比如n=24,那么 n/32=0,則24對(duì)應(yīng)在數(shù)組a中的下標(biāo)為0。又比如n=60,那么n/32=1,則60對(duì)應(yīng)在數(shù)組a中的下標(biāo)為1,同理可以計(jì)算0-N在數(shù)組a中的下標(biāo)。?
2.求0-N對(duì)應(yīng)0-31中的數(shù):?
十進(jìn)制0-31就對(duì)應(yīng)0-31,而32-63則對(duì)應(yīng)也是0-31,即給定一個(gè)數(shù)n可以通過模32求得對(duì)應(yīng)0-31中的數(shù)。?
3.利用移位0-31使得對(duì)應(yīng)32bit位為1.?
找到對(duì)應(yīng)0-31的數(shù)為M, 左移M位:即2^M. 然后置1.
由此我們計(jì)算10000000個(gè)bit占用的空間:
1byte =?8bit
1kb =?1024byte
1mb =?1024kb
占用的空間為:10000000/8/1024/1024mb。
大概為1mb多一些。
3、 擴(kuò)展?
??????? Bloom filter可以看做是對(duì)bit-map的擴(kuò)展?
4、 Bit-Map的應(yīng)用
? ? ??1)可進(jìn)行數(shù)據(jù)的快速查找,判重,刪除,一般來說數(shù)據(jù)范圍是int的10倍以下。
?????? 2)去重?cái)?shù)據(jù)而達(dá)到壓縮數(shù)據(jù)
5、 Bit-Map的具體實(shí)現(xiàn)
c語(yǔ)言實(shí)現(xiàn):
[cpp]?view plaincopyprint?
注明: 左移n位就是乘以2的n次方,右移n位就是除以2的n次方
解析本例中的void set(int i) {??????? a[i>>SHIFT] |=? (1<<(i & MASK)); }
1) ?i>>SHIFT:?
其中SHIFT=5,即i右移5為,2^5=32,相當(dāng)于i/32,即求出十進(jìn)制i對(duì)應(yīng)在數(shù)組a中的下標(biāo)。比如i=20,通過i>>SHIFT=20>>5=0 可求得i=20的下標(biāo)為0;
2) ?i & MASK:?
其中MASK=0X1F,十六進(jìn)制轉(zhuǎn)化為十進(jìn)制為31,二進(jìn)制為0001 1111,i&(0001 1111)相當(dāng)于保留i的后5位。?
比如i=23,二進(jìn)制為:0001 0111,那么?
???????????????????????? 0001 0111?
?????????????????? &??? 0001 1111 = 0001 0111 十進(jìn)制為:23?
比如i=83,二進(jìn)制為:0000 0000 0101 0011,那么?
????????????????????????? 0000 0000 0101 0011?
???????????????????? &?? 0000 0000 0001 0000 = 0000 0000 0001 0011 十進(jìn)制為:19?
i & MASK相當(dāng)于i%32。?
3) 1<<(i & MASK)?
相當(dāng)于把1左移 (i & MASK)位。?
比如(i & MASK)=20,那么i<<20就相當(dāng)于:?
???????? 0000 0000 0000 0000 0000 0000 0000 0001 << 20?
? ? ? ?=0000 0000 0001?0000 0000 0000 0000 0000?
注意上面 “|=”.
在博文:位運(yùn)算符及其應(yīng)用?提到過這樣位運(yùn)算應(yīng)用:
?將int型變量a的第k位清0,即a=a&~(1<<k)
?將int型變量a的第k位置1, 即a=a|(1<<k)
這里的將 ?a[i/32] |= (1<<M));?第M位置1 .
4) void set(int i) {??????? a[i>>SHIFT] ?|=? (1<<(i & MASK)); }等價(jià)于:
[cpp]?view plaincopyprint?
即實(shí)現(xiàn)上面提到的三步:
1.求十進(jìn)制0-N對(duì)應(yīng)在數(shù)組a中的下標(biāo):?n/32?
2.求0-N對(duì)應(yīng)0-31中的數(shù): N%32=M
3.利用移位0-31使得對(duì)應(yīng)32bit位為1: 1<<M,并置1;
php實(shí)現(xiàn)是一樣的:
[cpp]?view plaincopyprint?
0=11000000000000000000000000001110
1=1000001000000000000000010
6=10000000
32位表示,實(shí)際結(jié)果一目了然了,看看1,2,3,30,31, 33,50,56,199數(shù)據(jù)所在的具體位置:
? ? ? ?31 ? ?30 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3 ? ? 2 ? ? 1
? ? ? ?????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????
0= ? ?1 ? ? 1 ? ?00 ? ? ? 0000 ? 0000 ? 0000 ? 0000 ? ?0000 ? ? 0000 ? 1 ? ? 1 ? 1 ?0
? ? ? ? ? ? ? ? ? ? ? ? ??56 ? ? ? ? ? ? ? ? 50 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?33
? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????
1= ?0000 ? ? 0001 ? ?0000 ? 0100 ? 0000 ? ?0000 ? ? 0000 ? ?0010
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ?199
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???
6= ?0000 ?0000 ? ?0000 ? 0000 ? 0000 ? ?0000 ? ?1000 ? ?0000
【問題實(shí)例】
已知某個(gè)文件內(nèi)包含一些電話號(hào)碼,每個(gè)號(hào)碼為8位數(shù)字,統(tǒng)計(jì)不同號(hào)碼的個(gè)數(shù)。
8位最多99 999 999,大概需要99m個(gè)bit,大概10幾m字節(jié)的內(nèi)存即可。 (可以理解為從0-99 999 999的數(shù)字,每個(gè)數(shù)字對(duì)應(yīng)一個(gè)Bit位,所以只需要99M個(gè)Bit==1.2MBytes,這樣,就用了小小的1.2M左右的內(nèi)存表示了所有的8位數(shù)的電話)2)2.5億個(gè)整數(shù)中找出不重復(fù)的整數(shù)的個(gè)數(shù),內(nèi)存空間不足以容納這2.5億個(gè)整數(shù)。?
將bit-map擴(kuò)展一下,用2bit表示一個(gè)數(shù)即可,0表示未出現(xiàn),1表示出現(xiàn)一次,2表示出現(xiàn)2次及以上,在遍歷這些數(shù)的時(shí)候,如果對(duì)應(yīng)位置的值是0,則將其置為1;如果是1,將其置為2;如果是2,則保持不變。或者我們不用2bit來進(jìn)行表示,我們用兩個(gè)bit-map即可模擬實(shí)現(xiàn)這個(gè)2bit-map,都是一樣的道理。
實(shí)現(xiàn):
[cpp]?view plaincopyprint?
?// from:?http://blog.csdn.net/hguisu/article/details/7880288
總結(jié)
以上是生活随笔為你收集整理的海量数据处理算法—Bit-Map的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java输入输出流IO
- 下一篇: 从CVPR 2013看计算机视觉的研究领