哈希扩展【位图,布隆】,海量数据处理

位图:
它是用一个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

如果有什么不对的地方,可以评论告诉我,望指导!

猜你喜欢

转载自blog.csdn.net/phonycat/article/details/81321746