哈希扩展---布隆过滤器(bloom filter)

哈希扩展---布隆过滤器(bloom filter)

1>认识布隆过滤器:

可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。

使用多个Hash,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。

布隆过滤器的应用:网页URL的去重,垃圾邮件的判别,集合重复元素的判别,查询加速(比如基于key-value的存储系统)

吐舌头注意:对于布隆过滤器来说,存在不一定存在,但不存在一定不存在。

2>布隆过滤器实现:

BitMap.h

typedef struct BitMap
{
	int * Bit_bset;//位的集合
	int _capacity;
	int _size;//有效bit位的个数
}BitMap;
void BitMapInit(BitMap * bmp,int capacity);
void BitMapSet_zero(BitMap * bmp,int pos);
void BitMapSet_one(BitMap *bmp,int pos);
int  BitMapTest(BitMap *bmp, int pos);//测试bit位为1还是为0;
int BitMapSize(BitMap *bmp);
int BitMapCount(BitMap *bmp);
void BitMapDestroy(BitMap *bmp);

BitMap.c

#include "BitMap.h"
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
void BitMapInit(BitMap * bmp, int total_Bit){
	assert(bmp); //total_Bit代表总共的bit位数
	bmp->_capacity = (total_Bit >> 5 )+ 1;//代表需要的整形空间的个数
	bmp->Bit_bset = calloc(bmp->_capacity, sizeof(int));//void *calloc(空间的个数,每个空间的字节数);
	bmp->_size = total_Bit;//有效比特位的个数
}
//将pos的位置0;
void BitMapSet_zero(BitMap * bmp, int pos){
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	bmp->Bit_bset[pos_Byte] = bmp->Bit_bset[pos_Byte] &( ~(1 << pos));
	
}
//将pos的位置1;
void BitMapSet_one(BitMap *bmp, int pos){
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	bmp->Bit_bset[pos_Byte] = bmp->Bit_bset[pos_Byte] |(1 << pos);
	
}
int  BitMapTest(BitMap *bmp, int pos)//测试bit位为1还是为0;
{
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	return bmp->Bit_bset[pos_Byte] & (1 << pos);
}
int BitMapSize(BitMap *bmp)
{
	assert(bmp);
	return bmp->_size;
}
//统计bit位上1的个数
int BitMapCount(BitMap *bmp){
	int i = 0;
	int count = 0;
	assert(bmp);
	const char * bit1Count = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
	for ( i = 0; i <bmp->_capacity; i++)
	{
		int value = bmp->Bit_bset[i];
		int j = 0;
		//一个整数占4个字节,我们按一个字节为单元查看bit位上1的个数
		while (j<sizeof(bmp->Bit_bset[0])){
			char c = value;
			//统计一个字节的底4位
      		count+=bit1Count[c&0x0f];
			c >>= 4;
			//统计一个字节的高4位
			count+=bit1Count[c&0x0f];
			value >>= 8;
			j++;
		}
	}
	return count;
}
void BitMapDestroy(BitMap *bmp){
	assert(bmp);
	if (bmp->Bit_bset)
		free(bmp->Bit_bset);
	bmp->_size = 0;
	bmp->_capacity = 0;
}

BloomFilter.h

#include"BitMap.h"
typedef char* DataType;
typedef int(*pStrToInt)(char *str);
typedef struct BloomFilter{
	BitMap _bmp;
	int _size;
	pStrToInt _StrToInt_method[5];
}BloomFilter;

void BloomFilterInit(BloomFilter *bf, int capacity, pStrToInt *_StrToInt);
int StrToInt1(char *str);
int StrToInt2(char *str);
int StrToInt3(char *str);
int StrToInt4(char *str);
int StrToInt5(char *str);
void BloomFilterInsert(BloomFilter *bf, DataType str);
int IsIn(BloomFilter *bf, DataType str);

BloomFilter.c

#include "BloomFilter.h"
#include<stdlib.h>
#include<stddef.h>
#include<assert.h>
void BloomFilterInit(BloomFilter *bf, int size, pStrToInt _StrtoInt[5]){
	int i = 0;
	assert(bf);
	BitMapInit(&bf->_bmp,size*5);//一个元素对应5个bit位
	bf->_size = 0;
	for ( i = 0; i < 5; i++)
	{
		bf->_StrToInt_method[i] = _StrtoInt[i];
	}
}
int StrToInt1(char *str){
	unsigned int seed = 131; // 31 131 1313 13131 131313
	unsigned int hash = 0;
	while (*str)
	{
		hash = hash * seed + (*str++);
	}
	return (hash & 0x7FFFFFFF);
}
int StrToInt2(char *str){
	unsigned int hash = 0;
	int i;

	for (i = 0; *str; i++)
	{
		if ((i & 1) == 0)
		{
			hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));
		}
		else
		{
			hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));
		}
	}

	return (hash & 0x7FFFFFFF);
}
int StrToInt3(char *str){
	unsigned int hash = 5381;

	while (*str)
	{
		hash += (hash << 5) + (*str++);
	}

	return (hash & 0x7FFFFFFF);
}
int StrToInt4(char *str){
	unsigned int hash = 1315423911;

	while (*str)
	{
		hash ^= ((hash << 5) + (*str++) + (hash >> 2));
	}

	return (hash & 0x7FFFFFFF);
}
int StrToInt5(char *str){
	unsigned int hash = 0;
	unsigned int x = 0;

	while (*str)
	{
		hash = (hash << 4) + (*str++);
		if ((x = hash & 0xF0000000L) != 0)
		{
			hash ^= (x >> 24);
			hash &= ~x;
		}
	}

	return (hash & 0x7FFFFFFF);
}

void BloomFilterInsert(BloomFilter *bf,DataType str){
	int addr1, addr2, addr3, addr4, addr5;
	int TotalBits = bf->_bmp._size;
	addr1 = bf->_StrToInt_method[0](str) % TotalBits;
	BitMapSet_one(&bf->_bmp, addr1);
	addr2 = bf->_StrToInt_method[1](str) % TotalBits;
	BitMapSet_one(&bf->_bmp, addr2);
	addr3 = bf->_StrToInt_method[2](str) % TotalBits;
	BitMapSet_one(&bf->_bmp, addr3);
	addr4 = bf->_StrToInt_method[3](str) % TotalBits;
	BitMapSet_one(&bf->_bmp, addr4);
	addr5 = bf->_StrToInt_method[4](str) % TotalBits;
	BitMapSet_one(&bf->_bmp, addr5);
	bf->_size++;
}
int IsIn(BloomFilter *bf, DataType str){
	int addr1, addr2, addr3, addr4, addr5;
	int TotalBits = bf->_bmp._size;
	addr1 = bf->_StrToInt_method[0](str) % TotalBits;
	if (!BitMapTest(&bf->_bmp, addr1))
		return 0;
	addr2 = bf->_StrToInt_method[1](str) % TotalBits;
	if (!BitMapTest(&bf->_bmp, addr2))
		return 0;
	addr3 = bf->_StrToInt_method[2](str) % TotalBits;
	if (!BitMapTest(&bf->_bmp, addr3))
		return 0;
	addr4 = bf->_StrToInt_method[3](str) % TotalBits;
	if (!BitMapTest(&bf->_bmp, addr4))
		return 0;
	addr5 = bf->_StrToInt_method[4](str) % TotalBits;
	if (!BitMapTest(&bf->_bmp, addr5))
		return 0;
	return 1;
}


猜你喜欢

转载自blog.csdn.net/sx2448826571/article/details/80416589