哈希表这种数据结构能够非常快速的查找元素

但它的缺点是空间效率不高


位图提高了空间效率

但位图只能用来判断元素是否存在

关于位图的实现,在这里

http://zhweizhi.blog.51cto.com/10800691/1784383


下面简单介绍一下布隆过滤器。


现在,

假如通过哈希算法,将一个字符串转化成int类型的数据,

通过简单的线性探测(为什么不用其他方式,比如二次探测或者开链法呢?应该还是考虑了效率问题)存放在位图中,就能实现对字符串的查找了。

不过考虑到哈希冲突,用一个哈希算法肯定是不够的。 

可以考虑用多个哈希算法,将转化出的int类型数据映射到多个地方。


这样,在查找时,在通过之前用过的若干个哈希算法查找相应位置是否为'1' 

如果均为'1',那么很大概率上,这个字符串是存在的,

(因此布隆过滤器的判断存在并不是百分之百靠谱的,存在误判的概率,特别是随着元素数量越来越接近容量的时候,误判概率也会越来越高)

如果有一个为'0',那么就能肯定这个字符串是不存在的


实现的代码如下:
我采用了5个哈希算法,可以在网上找,找一些存活率高的。

然后将他们用仿函数实现:

struct __HashFunc1
{
	size_t SDBMHash(char *str)
	{
		size_t hash = 0;
		while (*str)
		{
			hash = (*str++) + (hash << 6) + (hash << 16) - hash;
		}
		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string &key)
	{
		return (SDBMHash((char*)key.c_str()));
	}
};
struct __HashFunc2
{
	unsigned int RSHash(char *str)
	{
		unsigned int b = 378551;
		unsigned int a = 63689;
		unsigned int hash = 0;

		while (*str)
		{
			hash = hash * a + (*str++);
			a *= b;
		}

		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string &key)
	{
		return (RSHash((char*)key.c_str()));
	}
};
struct __HashFunc3
{
	unsigned int RSHash(char *str)
	{
		unsigned int b = 378551;
		unsigned int a = 63689;
		unsigned int hash = 0;
		while (*str)
		{
			hash = hash * a + (*str++);
			a *= b;
		}
		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string &key)
	{
		return (RSHash((char*)key.c_str()));
	}
};
struct __HashFunc4
{
	unsigned int JSHash(char *str)
	{
		unsigned int hash = 1315423911;

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

		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string &key)
	{
		return (JSHash((char*)key.c_str()));
	}
};
struct __HashFunc5
{
	unsigned int PJWHash(char *str)
	{
		unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);
		unsigned int ThreeQuarters = (unsigned int)((BitsInUnignedInt * 3) / 4);
		unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);
		unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt - OneEighth);
		unsigned int hash = 0;
		unsigned int test = 0;

		while (*str)
		{
			hash = (hash << OneEighth) + (*str++);
			if ((test = hash & HighBits) != 0)
			{
				hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
			}
		}

		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string &key)
	{
		return (PJWHash((char*)key.c_str()));
	}
};



布隆过滤器:

//布隆过滤器
template<
class HashFunc1 = __HashFunc1,
class HashFunc2 = __HashFunc2,
class HashFunc3 = __HashFunc3,
class HashFunc4 = __HashFunc4,
class HashFunc5 = __HashFunc5
>
class BloomFillter
{
public:
	BloomFillter(size_t n)
		:_capacity(_GetNextPrime(n))
		,_bm(_capacity)
	{}

	void Set(const string &key)
	{
		size_t hash1 = HashFunc1()(key);
		size_t hash2 = HashFunc2()(key);
		size_t hash3 = HashFunc3()(key);
		size_t hash4 = HashFunc4()(key);
		size_t hash5 = HashFunc5()(key);
		_bm.Set(hash1 % _capacity);
		_bm.Set(hash2 % _capacity);
		_bm.Set(hash3 % _capacity);
		_bm.Set(hash4 % _capacity);
		_bm.Set(hash5 % _capacity);

	}

	bool Test(const string &key)
	{
		size_t hash1 = HashFunc1()(key);
		if (!_bm.Test(hash1 % _capacity))
		{
			return false;
		}
		size_t hash2 = HashFunc2()(key);
		if (!_bm.Test(hash2 % _capacity))
		{
			return false;
		}
		size_t hash3 = HashFunc3()(key);
		if (!_bm.Test(hash3 % _capacity))
		{
			return false;
		}
		size_t hash4 = HashFunc4()(key);
		if (!_bm.Test(hash4 % _capacity))
		{
			return false;
		}
		size_t hash5 = HashFunc5()(key);
		if (!_bm.Test(hash5 % _capacity))
		{
			return false;
		}
		return true;
	}


protected:
	size_t _GetNextPrime(size_t n)
	{
		const int _PrimeSize = 28;
		static const unsigned long _PrimeList[_PrimeSize] =
		{
			53ul,         97ul,         193ul,       389ul,       769ul,
			1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
			49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
			1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
			50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
			1610612741ul, 3221225473ul, 4294967291ul
		};
		for (int i = 0; i < _PrimeSize; ++i)
		{
			if (_PrimeList[i] > n)
			{
				return _PrimeList[i];
			}
		}
		return n;
	}
protected:
	size_t _capacity;
	BitMap _bm;
};