码迷,mamicode.com
首页 > 其他好文 > 详细

布隆过滤器

时间:2016-07-05 06:30:45      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:哈希函数

  • 什么是布隆过滤器

    布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。

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

  • 实现思想

   如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。

   Hash面临的问题就是冲突。假设Hash函数是良好的,如果我们的位阵列长度为m个点,那么如果我们想将冲突率降低到例如 1%, 这个散列表就只能容纳m / 100个元素。显然这就不叫空间效率了(Space-efficient)了。解决方法也简单,就是使用多个Hash函数,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。

  • 代码实现

    Bloom Filter.h

#pragma once
#include"HashFunc.h"
template<class K=int,
class HashFunc1 = _HashFunc1<K>,
class HashFunc2 = _HashFunc2<K>,
class HashFunc3 = _HashFunc3<K>,
class HashFunc4 = _HashFunc4<K>, 
class HashFunc5 = _HashFunc5<K>>
class BloomFilter
{
public:
	BloomFilter(size_t size)
	{
		_bm.Resize(size);
	}
	void Set(K key)
	{
		_HashFunc1<K> hf1;
		_HashFunc1<K> hf2;
		_HashFunc1<K> hf3;
		_HashFunc1<K> hf4;
		_HashFunc1<K> hf5;
		size_t index1 = hf1(key);
		size_t index2 = hf2(key);
		size_t index3 = hf3(key);
		size_t index4 = hf4(key);
		size_t index5 = hf5(key);
		_bm.Set(index1);
		_bm.Set(index2);
		_bm.Set(index3);
		_bm.Set(index4);
		_bm.Set(index5);
		++_capacity;
	}
	//布隆过滤器不能执行删除操作,因为有不同的哈希算法,可能不同的key
	//标记在相同的位上,删除会把别人的记录给删除了,影响正确性。
	//void Reset(const K& key);

	//测试存在不一定存在,不存在一定不存在
	bool Test(const K& key)
	{
		_HashFunc1<K> hf1;
		_HashFunc1<K> hf2;
		_HashFunc1<K> hf3;
		_HashFunc1<K> hf4;
		_HashFunc1<K> hf5;
		size_t index1 = hf1(key);
		size_t index2 = hf2(key);
		size_t index3 = hf3(key);
		size_t index4 = hf4(key);
		size_t index5 = hf5(key);
		if (_bm.Test(index1) && _bm.Test(index2) &&
			_bm.Test(index3) && _bm.Test(index4) &&
			_bm.Test(index5))
			return true;
		else
			return false;
	}
protected:
	BitMap<K> _bm;
	size_t _capacity;
};

BitMap.h
#pragma once
//数据类型的仿函数
template<class T>
struct DataType
{
	long long operator()(const T&key)
	{
		return key;
	}
};
//字符串类型的仿函数
template<class T>
struct StringType
{
	long long operator()(const string&key)
	{
		long long size = 0;
		for (int i = 0; i < key.size(); i++)
		{
			size += key[i];
		}
		return size/(key.size());
	}
};
template<class T,template<class T>class BMFunc=DataType>
class BitMap
{
public:
	BitMap(size_t size = 1)
	{
		_a.resize(size / 32 + 1);
	} 
	
	~BitMap(){}
	void Resize(size_t size)
	{
		_a.resize(size / 32 + 1);
	}
	void Set(const T& x)
	{
		BMFunc<T>bmf;
		size_t index = bmf(x)/ 32;
		size_t num = bmf(x) % 32;
		if (!(_a[index] & (1 << num)))
		{
			_a[index] |= (1 << num);
			_size++;
		}
		
	}
	void Reset(const T&x)
	{
		BMFunc<T>bmf;
		size_t index = bmf(x) / 32;
		size_t num = bmf(x) % 32;
		if (!(_a[index] & (1 << num)))
		{
			_a[index] &= (~(1 << num));
			_size--;
		}
	}
	bool Test(T x)
	{
		BMFunc<T> bmf;
		size_t index = bmf(x)/ 32;
		size_t num = bmf(x)% 32;
		return _a[index]&(1 << num);
	}
protected:
	vector<size_t> _a; 
	size_t _size;
};

HashFunc.h

//5个高效的哈希算法
template<class T>
// BKDR Hash Function是一种简单快捷的hash算法,
//也是Java目前采用的字符串的Hash算法(累乘因子为31)
struct  _HashFunc1
{
	size_t operator()(const T& str)
	{
		register size_t hash = 0;
		const char *tmp = str.c_str();
		while (size_t ch = (size_t)*tmp++)
		{
			while (size_t ch = (size_t)*tmp++)
			{
				hash = hash * 131 + ch;
			}
			return hash;
		}
	}
};
template<class T>
//RS Hash Function。因Robert Sedgwicks在其《Algorithms in C》一书中展示而得名。
struct _HashFunc2
{
	size_t operator()(const T& str)
	{
		register size_t hash = 0;
		size_t magic = 63689;
		const char* tmp = str.c_str();
		while (size_t ch = (size_t)*tmp++)
		{
			hash = hash * magic + ch;
			magic *= 378551;
		}
		return hash;
	}
}; template<class T>
//AP Hash Function 由Arash Partow发明的一种hash算法。
struct _HashFunc3
{
	size_t operator()(const T& str)
	{
		register size_t hash = 0;
		size_t ch;
		const char* tmp = str.c_str();
		for (long i = 0; ch = (size_t)*tmp++; i++)
		{
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
			}
		}
		return hash;
	}
};

template<class T>
// DJB Hash Function 2。由Daniel J. Bernstein 发明的另一种hash算法。
struct _HashFunc4
{
	size_t operator()(const T& str)
	{
		const char* tmp = str.c_str();
		if (!*tmp)   // 这是由本人添加,以保证空字符串返回哈希值0  
			return 0;
		register size_t hash = 5381;
		while (size_t ch = (size_t)*tmp++)
		{
			hash = hash * 33 ^ ch;
		}
		return hash;
	}
};

template<class T>
//JS Hash Function 。由Justin Sobel发明的一种hash算法。
struct _HashFunc5
{
	size_t operator()(const T& str)
	{
		const char* tmp = str.c_str();
		if (!*tmp)        // 这是由本人添加,以保证空字符串返回哈希值0  
			return 0;
		register size_t hash = 1315423911;
		while (size_t ch = (size_t)*tmp++)
		{
			hash ^= ((hash << 5) + ch + (hash >> 2));
		}
		return hash;
	}
};


 



本文出自 “学习记录” 博客,转载请与作者联系!

布隆过滤器

标签:哈希函数

原文地址:http://10794428.blog.51cto.com/10784428/1795758

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!