位图,布隆过滤器,哈希分割

文章介绍了位图作为数据结构用于高效存储和查询大量数据,以及布隆过滤器的概念,它利用多次哈希映射减少空间需求,允许一定的误判率。布隆过滤器常用于网络爬虫、垃圾邮件过滤和搜索引擎优化等场景。此外,文章还提到了哈希分割在处理大数据时的作用,通过哈希函数将数据分片,提高统计效率。
摘要由CSDN通过智能技术生成

🚀位图

学习位图前,我们先来看一道题
在这里插入图片描述

  • 用哈希表存储每个整数?不行,数量太大了,存储不下这么多数据。
  • 对这些整数先排序,在用二分查找?也不行,同理,数据量太大了,不好存储数据,排序都能成问题,更何况来查找。
  • 遍历一遍。当然这个是可以的,但是题目是快速,所以时间还是慢了。

好的,这里就慢慢引出今天的主角,位图。

💡概念

位图是一种数据结构,用于表示一个二进制数组中的位或标记


位图通常是一个非常紧凑的数据结构,可以通过一个位来表示一个存储单元。例如,如果一个位图有8个位,那么可以用一个字节表示它们,如果有32个位,那么可以用一个4字节的数据表示它们。


位图的特点是可以高效地进行位运算,例如按位与、按位或、按位取反、按位移动等。因为这些运算都只需要单个 CPU 周期,所以位图非常适合于高性能计算和大型数据集合的处理。

💡接口操作

C++中是有位图的库,我们只需要包头文件 #include< bitset > 即可使用在这里插入图片描述

这里先简单认识一下常用的bitset的接口函数
在这里插入图片描述

set(n) -------- 将第n个比特位设置为1
reset(n) ----- 将第n个比特位设置为0
test(n) ------- 检查第n个比特位,是1返回真,0返回假

那么我们回到题目
用位图来存储每个数字的状态,0表示不在,1表示在,每个比特位表示一个数字,就是有40亿个数(约等于232bit ≈ 4GB大小)也可以装得下,而且查找的时间复杂度是O(1),快的起飞。

🚀布隆过滤器

💡思想

我们知道哈希表是调用一次哈希函数映射到表里的,而布隆过滤器也是这个思想,只不过是多次进行哈希映射,且映射到位图里
在这里插入图片描述
在这里插入图片描述
图片转载

  • 假设 jingdong 映射的是 1 2 3上的比特位,我们在查询的时候发现2号为0,这时候我们可以肯定 jingdong 这个值一定不存在,而我们查询baidu,发现 1 4 7上的比特位都为1,这个时候我们能认为baidu就一定存在吗?答案是否定的,只是可能存在因为不排除其他值的组合恰好凑成了 1 4 7上的比特位为1
  • 布隆过滤器的删除
    布隆过滤器一般是不建议删除的,就算用计数,也会影响到其他值的存在,因为删除操作会增加误判率,所以一般是不建议删除的,如果需要可以根据具体使用场景来实现支持删除的布隆过滤器。

💡实现代码

struct BKDRHash
{
	size_t operator()(const string& s)
	{
		// BKDR
		size_t value = 0;
		for (auto ch : s)
		{
			value *= 31;
			value += ch;
		}
		return value;
	}
};
struct APHash
{
	size_t operator()(const string& s)
	{
		size_t hash = 0;
		for (long i = 0; i < s.size(); i++)
		{
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ s[i] ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ s[i] ^ (hash >> 5)));
			}
		}
		return hash;
	}
};
struct DJBHash
{
	size_t operator()(const string& s)
	{
		size_t hash = 5381;
		for (auto ch : s)
		{
			hash += (hash << 5) + ch;
		}
		return hash;
	}
};
struct JSHash
{
	size_t operator()(const string& s)
	{
		size_t hash = 1315423911;
		for (auto ch : s)
		{
			hash ^= ((hash << 5) + ch + (hash >> 2));
		}
		return hash;
	}
};
template<size_t N,
	class K = string,
	class HashFunc1 = BKDRHash,
	class HashFunc2 = APHash,
	class HashFunc3 = DJBHash,
	class HashFunc4 = JSHash>
class bloomfilter
{
private:
	bitset<N> _bs;
public:
	void set(const K& key)
	{
		size_t n1 = HashFunc1()(key) % N;
		size_t n2 = HashFunc2()(key) % N;
		size_t n3 = HashFunc3()(key) % N;
		size_t n4 = HashFunc4()(key) % N;

		_bs.set(n1);
		_bs.set(n2);
		_bs.set(n3);
		_bs.set(n4);
	}
	bool test(const K& key)
	{
		size_t n1 = HashFunc1()(key) % N;
		size_t n2 = HashFunc2()(key) % N;
		size_t n3 = HashFunc3()(key) % N;
		size_t n4 = HashFunc4()(key) % N;

		if (_bs.test(n1) && _bs.test(n2) && _bs.test(n3) && _bs.test(n4))
			return true;
		return false;
	}

	// 一般不实现,因为BloomFilter采用多重哈希映射,就决定了还原的时候必然会影响到其他值
	bool reset(const K& key);
};

💡实际应用

布隆过滤器常用于需要快速判断某个元素是否存在于一个集合中的场景,尤其适用于数据量庞大、查询频繁的情况。以下是一些具体的实际应用:

  1. 网络爬虫优化:网络爬虫需要快速判断一个网页是否已经爬取过,以避免重复爬取。使用布隆过滤器可以快速判断一个网页是否已经爬取过,避免重复爬取。

  2. 垃圾邮件过滤:垃圾邮件过滤需要快速判断一封邮件是否是垃圾邮件。使用布隆过滤器可以将一些常见的垃圾邮件关键词或者特征加入到集合中,用于快速判断待过滤的邮件是否属于垃圾邮件。

  3. 搜索引擎索引优化:在搜索引擎索引过程中,需要快速判断一个单词是否出现在某个网页中。使用布隆过滤器可以将某个单词的哈希值加入到集合中,用于快速判断该单词是否出现在某个网页中。

  4. 大规模缓存数据的快速查询:在缓存数据中,如果需要快速判断某个键是否存在于缓存中,可以使用布隆过滤器来实现快速查询。

总的来说,布隆过滤器在需要快速判断某个元素是否在一个集合中时具有广泛的应用价值,特别是在数据量庞大、查询频繁的场景下,其效果更为明显。

🚀哈希分割

牛客上看到一个很有意思的题目和解法
如图:
在这里插入图片描述
题目网址

解法:

  1. 100G的文件,我们可以分为100种小文件进行统计,其中分发是按照哈希函数来划分,这样可以确保统一类型的ip地址在一个小文件里,而不是分散在各个文件中。
  2. 对每个小文件用unordered_map<string,int> map来进行哈希统计,并统计出最大的,然后map.clear()
  3. 重复步骤二100次,就可以找到出现次数最多的ip地址了

如果要找topK,那就定义优先级队列(小根堆),大的就进队,这样就能拿到topK个了

原理就是:用哈希函数来对数据进行划分范围,做到具有相同属性的值在同一区域内

位图(Bitmap)和布隆过滤器(Bloom Filter)都是常用的数据结构,用于处理大规模数据集合,但它们有着不同的应用场景和用途。 位图是一种压缩数据结构,用于快速地判断某个元素是否在集合中。位图的实现方式是将每个元素映射到一个二进制位上,如果该元素存在于集合中,则将对应的二进制位标记为1,否则标记为0。这样,当需要查询某个元素是否在集合中时,只需要查找对应的二进制位即可。由于位图的实现方式非常简单,因此可以快速地进行插入和查询操作,而且占用的空间也非常小,适合处理大规模数据集合。 布隆过滤器也是一种快速判断元素是否存在于集合中的数据结构,但其实现方式与位图略有不同。布隆过滤器使用一组哈希函数将元素映射到多个二进制位上,并将对应的二进制位标记为1。当查询某个元素是否在集合中时,将该元素进行哈希映射,并查找对应的二进制位,如果所有的二进制位都被标记为1,则说明该元素可能存在于集合中,否则可以确定该元素不存在于集合中。布隆过滤器的优点是可以快速地判断一个元素不存在于集合中,而且占用的空间也比较小,但存在误判率的问题。 因此,位图布隆过滤器虽然都可以用来处理大规模数据集合,但它们的实现方式和应用场景有所不同。位图适用于需要快速地判断某个元素是否在集合中的场景,而布隆过滤器适用于需要快速地判断一个元素不存在于集合中的场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值