Url排重Bloom Filter 算法、误差及其他

本文探讨了BloomFilter算法在Url排重中的应用及其误差特性,介绍了该算法如何通过一组Hash算法将集合中的元素转换为位表示,实现快速查询的同时节省空间。并讨论了误差与效率之间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Url排重Bloom Filter 算法、误差及其他

fly with me , in the perfect world --- 题记


最近看了一些书,公式和算法,用一个词把他们窜起来的话,这就是:误差。说起误差,这让我想起了小时候的一个故事。小时候有个朋友他家在二级路旁开了家小商店。有一天客户拿着刚买的散装油对他说:分量不够。他告诉客户:这是误差。客户很生气说分量不够就是不够,怎么是误差?我这个朋友还真有办法,拉客户到隔壁,把油放到地秤上,说:你看把这壶油有放在地秤(称汽车的地称)上,地秤没显示,这就是误差。

小时候的事情,印象很深。

现在想起来,对误差的理解也更多了一些。不同的标准,不同的场合,不同的期望,这些通通构成了误差。可以说我们时时刻刻都被误差包围着。甚至在管理上,方兴东在博客上也总结说:对误差的极度容忍是一个管理者的必备素质。我自己也总结了一下:医学是对模糊的精确控制,管理是对精确的模糊管理。

我这里说说误差和效率的一点关系。误差和效率是一对矛盾共同体,生活中有对误差和效率的关系描述:“萝卜快了,不洗泥”;“慢工出细活”等等,都精辟的说出了误差和效率的辨证关系。对软件工程师来说,特别是编写算法的时候,对于“空间换时间”和“时间换空间”已经耳熟能详了;我想还应该加上一句:误差换效率。

误差换效率

google黑板报上一片文章,讲Url排重用到的一个技巧:把平均长度较长的Url转换成平均长度较短的GUID来节省空间。在Url排重方面还有一个常用的算法:Bloom Filter 算法。Bloom Filter 算法是查看元素E是否在集合S中存在的快速算法,典型的应用就是拼写检查spellcheck时,查看某个单词是否在字典中存在。关于查询的算法有很多种了,排序折半、B-Tree、Hash-Code 等等。Bloom Filter 的优点是什么呢?
1、Bloom Filter不存储key-value值,Bloom Filter 用一组Hash算法把集合S中的元素E换算成位表示;
2、查询速度快。

我们知道Hash算法一般都有冲突,在Bloom Filter中的冲突就表现为误差了。

Bloom Filter 是一种常见的算法,现在已经有了 Java , C++ , C# , ruby 等各个版本的算法。当然也有很多变种出现以适应更多的需求。
Bloom Filter 是有误差的,但误差在可控制的程度内。换句话说,大多数的误差的恼人之处在于我们无法衡量它。

参考阅读:


http://blog.likeshow.net/article.asp?id=34
http://blogs.msdn.com/devdev/archive/2006/01/23/516431.aspx
http://en.wikipedia.org/wiki/Type_I_and_type_II_errors
http://en.wikipedia.org/wiki/Bloom_filter

http://jaspell.sourceforge.net/javadocs/index-files/index-2.html
http://blogs.msdn.com/devdev/archive/2005/08/17/452827.aspx
http://www.cc.gatech.edu/fac/Pete.Manolios/research/bloom-filters-verification.html
http://homepages.inf.ed.ac.uk/s9902505/specksim/doc/index-files/index-2.html
http://weblogs.asp.net/dfindley/archive/2004/08/19/217485.aspx
http://www.darkridge.com/~jpr5/archive/dads/HTML/bloomFilter.html
http://loaf.cantbedone.org/





<think>嗯,用户这次在询问C++中布隆过滤器的实现与演示代码,并且引用了站内的几个相关引用内容。根据引用[2],用户已经了解布隆过滤器的基本概念特点,比如二进制向量、随机映射函数、空间效率高等。用户可能正在开发需要高效去的系统,比如爬虫URL检测或缓存系统。用户提供的引用中包含线程安全的LRU缓存代码(引用[1])、布隆过滤器理论说明(引用[2])、算法实现(引用[3])以及位图操作(引用[4])。其中引用[4]的位图置函数reset()尤其要,因为位图正是布隆过滤器的核心存储结构。布隆过滤器的实现关键点有三个:位数组大小(m)、哈希函数数量(k)、哈希种子选择。引用[2]提到布隆过滤器误差概率特性,这提醒我需要强调参数设计对误判率的影响。用户作为C++开发者,应该需要可运行的实际代码而非伪代码。在回复中,应当包含位数组的实现(参考引用[4]的位操作技术)、多个哈希函数设计(如不同种子)、插入查询接口。由于用户引用过线程安全代码(引用[1]),可能需要考虑并发场景下的加锁机制。但核心演示可暂不涉及线程安全,保持代码简洁。最后需要提醒用户布隆过滤器的典型缺陷:不可删除、存在误判。这可以通过引用[2]提到的“概率性结果”来佐证。实践建议部分将补充空间计算场景选择,避免用户误用于需要精确删除的场景。</think> 以下是C++中布隆过滤器的实现与演示代码,结合引用内容中的技术要点解析: ### 布隆过滤器核心实现 ```cpp #include <bitset> #include <functional> #include <vector> class BloomFilter { private: std::bitset<10000> bit_array; // 位数组(引用[4]的位操作基础) std::vector<std::hash<std::string>> hash_functions; // 哈希函数集合(引用[2]的"一系列随机映射函数") public: BloomFilter(int hash_count) { for (int i = 0; i < hash_count; ++i) { // 使用不同种子创建多个哈希函数(降低误判率) std::hash<std::string> hash_func; hash_functions.push_back(hash_func); } } // 添加元素(引用[2]的"高效插入") void add(const std::string& item) { for (auto& hash_func : hash_functions) { size_t hash_val = hash_func(item); size_t index = hash_val % bit_array.size(); bit_array.set(index); // 置位对应位置(引用[4]的位操作) } } // 检查元素(引用[2]的"可能存在/一定不存在"特性) bool contains(const std::string& item) const { for (auto& hash_func : hash_functions) { size_t hash_val = hash_func(item); size_t index = hash_val % bit_array.size(); if (!bit_array.test(index)) { return false; // 任一位置未置位则必然不存在 } } return true; // 所有位置均置位则可能存在(有误判概率) } }; ``` ### 演示代码 ```cpp #include <iostream> int main() { // 创建含3个哈希函数的布隆过滤器(引用[2]的"概率性结果"特性) BloomFilter filter(3); filter.add("https://example.com/page1"); filter.add("https://example.com/page2"); std::cout << "Check page1: " << filter.contains("https://example.com/page1") // 输出1 (存在) << std::endl; std::cout << "Check unknown: " << filter.contains("https://example.com/unknown") // 可能输出0或1 (存在误判概率) << std::endl; } ``` ### 核心特性解析(引用[2]的要点) 1. **空间效率** 位数组存储代替传统数据结构(引用[2]的*"占用空间更少"*) 2. **误差特性** 当`contains()`返回`true`时可能存在误判,返回`false`时元素必然不存在 3. **无删除操作** 直接删除位会导致其他元素失效(引用[2]的*"一般不提供删除操作"*) 4. **哈希函数数量** 增加哈希函数数量可降低误判率,但会增大计算开销(需权衡) ### 参数设计建议 1. 位数组大小 `m` 与预期元素数量 `n` 的关系: $$ m = -\frac{n \ln p}{(\ln 2)^2} $$ (其中 $p$ 为可接受的误判概率) 2. 最优哈希函数数量 `k`: $$ k = \frac{m}{n} \ln 2 $$ ### 实践建议 1. **适用场景**(引用[2]的应用案例): - URL爬虫去(检测新链接) - 缓存击穿防护(快速过滤无效请求) - 拼写检查器(单词存在性校验) 2. **注意事项**: - 需要预估最大数据量来设定位数组大小 - 对精度要求高的场景需配合二级校验 - C++11+标准中可使用`std::hash`的默认特化[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值