雜湊擴充套件【點陣圖,布隆】,海量資料處理
阿新 • • 發佈:2019-02-03
點陣圖:
它是用一個bit位來標識一個整數存在或者不存在,一般用於大資料的簡單確認是否存在
類似於雜湊的直接定址法,只不過點陣圖定在了一個位上,用bit上的0和1來標識一個數字存在或者不存在哈哈
typedef struct BitMap
{
size_t* _bits;
size_t _range;
}BitMap;
//點陣圖的初始化
void BitMapInit(BitMap* bf, size_t range)
{
bf->_range = range;
bf->_bits = (size_t*)malloc(sizeof(size_t)*((range >>5 ) + 1));
memset(bf->_bits, 0, sizeof(size_t)*((range >> 5) + 1));
}
//點陣圖的銷燬
void BitMapDestory(BitMap* bm)
{
free(bm->_bits);
}
//將x對應位置為1
void BitMapSet(BitMap* bf, size_t x)
{
size_t index = x >> 5;
size_t num = x % 32;
bf->_bits[index] |= (1 << num);
}
//將x對應位重置為0
void BitMapRest(BitMap* bf, size_t x)
{
size_t index = x >> 5;
size_t num = x % 32;
bf->_bits[index] &= (~(1 << num));
}
//判斷x是否存在,x存在返回0,不存在返回-1
int BitMapTest(BitMap* bf, size_t x)
{
size_t index = x >> 5;
size_t num = x % 32;
if (bf->_bits[index] & (1 << num)!=0)
return 0;
else
return -1;
}
布隆過濾器:
- 點陣圖用於判斷整形是否存在,布隆過濾器用於判斷任何型別是否存在,不存在是確定的,但是存在可能會出現誤判
- 布隆過濾器的本質上還是點陣圖
- 布隆過濾器將一個字串用多個雜湊函式映射出多個位置,將這多個位置都置為1,才算是存在
- 多個位判斷一個值存在不存在,嚴格來說,只能進不能出,如果因為一個值不存在了,將它對應的位置0,那這個位可能有多個數同時對映到這裡,這樣就出問題了。
- 一個值對應多個位,如果要查詢一個值,它不存在,但是它對應的位恰巧都是1 ,那麼這時候就存在誤判了
typedef const char* KeyValue;
typedef char* KeyType;
typedef size_t(*HASH_FUNC)(KeyType str);
typedef struct BloomFilter
{
BitMap _bm;
HASH_FUNC _hashfunc1;
HASH_FUNC _hashfunc2;
HASH_FUNC _hashfunc3;
}BloomFilter;
//雜湊函式1
size_t BKDRHash(KeyType str)
{
size_t hash = 0;
while (size_t ch = (size_t)* str++)
{
hash = hash * 131 + ch;
}
return hash;
}
//雜湊函式2
size_t SDBMHash(KeyType str)
{
size_t hash = 0;
while (size_t ch = (size_t)*str++)
{
hash = 65599 * hash + ch;
}
return hash;
}
//雜湊函式3
size_t RSHash(KeyType str)
{
size_t hash = 0;
size_t magic = 63689;
while (size_t ch = (size_t)*str++)
{
hash = hash*magic + ch;
magic *= 378551;
}
return hash;
}
//布隆過濾器的初始化
int BloomFilterInit(BloomFilter* bf,size_t range)
{
assert(bf);
BitMapInit(&bf->_bm, range);
bf->_hashfunc1 = BKDRHash;
bf->_hashfunc2 = SDBMHash;
bf->_hashfunc3 = RSHash;
}
//布隆過濾器一個值對應的位,雜湊對映,置為1
void BloomFilterSet(BloomFilter* bf, KeyType key)
{
assert(bf);
size_t range = bf->_bm._range;
size_t hash1 = bf->_hashfunc1(key);
size_t hash2 = bf->_hashfunc2(key);
size_t hash3 = bf->_hashfunc3(key);
BitMapSet(&bf->_bm, hash1%range);
BitMapSet(&bf->_bm, hash2%range);
BitMapSet(&bf->_bm, hash3%range);
}
//判斷一個值是否存在,x存在返回0,不存在返回-1
int BloomFilterTest(BloomFilter* bf, KeyType key)
{
size_t range = bf->_bm._range;
size_t hash1 = bf->_hashfunc1(key);
if (BitMapTest(&bf->_bm, hash1%range) == -1)
return -1;
size_t hash2 = bf->_hashfunc2(key);
if (BitMapTest(&bf->_bm, hash2%range) == -1)
return -1;
size_t hash3 = bf->_hashfunc3(key);
if (BitMapTest(&bf->_bm, hash3%range) == -1)
return -1;
return 0;//存在誤判
}
//一個值不存在了,將它的位置為0
int BloomFilterReset(BloomFilter* bf, KeyType key)
{
//暫時不能實現,會影響其他的值
}
//布隆過濾器的銷燬
void BloomFilterDestory(BloomFilter* bf)
{
BitMapDestory(&bf->_bm);
}
海量資料處理:
給一個超過100G大小的檔案,裡面存著IP地址,設計演算法找到出現次數最多的IP地址
100G太大,計算機記憶體有限,可以把它切分成多個小檔案進行操作。
次數,可以是雜湊,相同的IP對映到同一個小檔案中。
- 100G的檔案切分成100或是更多1000個小檔案
- 每個檔案中IP對映到雜湊表中,雜湊的key-value模型
- 相同的IP肯定進入相同的檔案,在對這個檔案統計次數,一次統計,如果比之前大,就更新
給100億個整數,設計演算法找到只出現一次的整數
整數有三種狀態:出現0次,1次,多次
100億的整數,佔記憶體40G,計算機記憶體勢必不夠,雜湊點陣圖啊
- 和上面內個一樣,切分,統計出出現一次的
- 採用點陣圖,兩個位標識一個數,00不存在,01出現一次,10出現多次
給兩個檔案,分別有100億個整數,我們只有1G記憶體,如何找到兩個檔案的交集
- 把100億個數放到一個位圖裡(500M),遍歷另一個檔案,存在的話即就是交集
- 先把一個檔案存到位圖裡,將另一個檔案構成點陣圖與第一個點陣圖按位與一下
一個檔案有100億個整數,1G記憶體,設計演算法找到次數不超過2次的所有整數
- 一個位圖兩個位置描述一個數,00不存在,01出現一次,10兩次,11多次,超過兩次
給兩個檔案,分別有100億個query,只有1G記憶體,如何找到兩個檔案交集?
- 近似演算法:布隆,建立一個布隆,把其中一個所有字串都扔進這個布隆裡,再拿另一個來查,不在的一定不是交集,在的不一定是交集
- 精確:假設一個query佔20bytes,100億query即200G,進行雜湊切分分成1000份,A中的query進入A小檔案,求A0 B0的交集,求A1 B1的交集,求A2 B2的交集,,,
如何拓展布隆過濾器使得它支援刪除元素的操作
- 引用計數,一個位可能有多個值在這裡對映,對這個位進行引用計數,進行刪除時,先判斷它的引用計數,如果引用計數不為1,引用計數–,否則將該位置0,並且引用計數置0
如果有什麼不對的地方,可以評論告訴我,望指導!