哈希表—位圖
[1.什麽是位圖?<br/>2.位圖的用處?<br/>3.位圖的結構<br/>4.位圖題目操練<br/>5.總結(優缺點分析)]
1.什麽是位圖?
位圖就是bitmap的縮寫。所謂bitmap,就是用每一位來存放某種狀態,適用於大規模數據,但數據狀態又不是很多的情況。通常是用來判斷某個數據存不存在的。在STL中有一個bitset容器,其實就是位圖。
所以我們可以了解到,位圖就是一個只用每一位來保存數的狀態的結構。
2.位圖的用處?
位圖主要用於海量數據處理,索引,數據壓縮等方面有廣泛應用
關於位圖的結構,類似於哈希,位圖就是一個用每一位的0,1來表示一個數的狀態。
比如,我們現在有一個文件,這個文件中有數 1,5,4294967295。我們就把第1位,第5位,第4294967295位改為狀態1。
4.位圖題目操練
給4 0 億個不重復的無符號整數,沒排過序。給一個無符號整數,如何快速判斷一個數是否在這4 0 億個數中。
題目分析:這是一道關於海量數據查找的題,其實這道題,我們就可以和哈希表聯系在一起,為何說是海量數據呢,對於一個40億整數,我們如果要存的話,按照無符號整數來存儲,那麽下來,大概就需要40億*4這麽些字節,下來大概就是16G的 內存。
對於現在的64位機,普遍標配內存也就是4-8G的內存,顯而易見,16G是沒有辦法一次性處理的。那麽我們如何是好?進行拆分?這樣顯然也是不好的,怎麽拆,還有效率問題。
位圖結構定義
typedef struct BitMap
{
size_t* _bits;
size_t _range;
}BitMap;
位圖相關接口
void BitMapInit(BitMap *bm,size_t range) //初始化 { assert(bm); bm->_bits = NULL; bm->_range = range; bm->_bits = (size_t *)malloc(sizeof(char)*bm->_range/8); assert(bm->_bits); memset(bm->_bits,0,sizeof(char)*bm->_range/8); } void BitMapSet(BitMap *bm,size_t x)//標記相應位 { size_t num = x>>5; size_t bit = x%32; bm->_bits[num] |=(1<<bit); } void BitMapReset(BitMap *bm,size_t x)//恢復相應位 { size_t num = x>>5; size_t bit = x%32; bm->_bits[num] &= (~(1<<bit)); } int BitMapTest(BitMap *bm,size_t x) { size_t num = x>>5; size_t bit = x%32; if ((1<<bit)&bm->_bits[num]) return 0; return -1; }
測試案例及結果截圖:
void TestBitMap()
{
BitMap bm;
BitMapInit(&bm,-1);
BitMapSet(&bm,5);
BitMapSet(&bm,6);
BitMapSet(&bm,7);
BitMapSet(&bm,8);
BitMapSet(&bm,-1);
printf("%d\n",BitMapTest(&bm,4));
printf("%d\n",BitMapTest(&bm,5));
printf("%d\n",BitMapTest(&bm,6));
printf("%d\n",BitMapTest(&bm,7));
printf("%d\n",BitMapTest(&bm,8));
printf("%d\n",BitMapTest(&bm,-1));
}
這道題中位圖結構代碼不難,註意理解思路,必須熟練掌握位運算。
5.總結
優缺點:
(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 。
哈希表—位圖