1. 程式人生 > >雜湊擴充套件【點陣圖,布隆】,海量資料處理

雜湊擴充套件【點陣圖,布隆】,海量資料處理

點陣圖:
它是用一個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

如果有什麼不對的地方,可以評論告訴我,望指導!