0

0

C++怎么实现一个布隆过滤器_C++海量数据去重与概率性数据结构

尼克

尼克

发布时间:2025-11-28 15:01:02

|

449人浏览过

|

来源于php中文网

原创

布隆过滤器是一种高效判断元素是否可能存在于集合中的概率性数据结构,由位数组和多个哈希函数构成;插入时将k个哈希位置设为1,查询时若所有位均为1则可能存在,否则一定不存在;C++实现采用vector存储,通过双重哈希生成多值,结合最优m和k参数控制误判率,适用于去重、缓存防穿透等场景,但不支持删除且存在假阳性。

c++怎么实现一个布隆过滤器_c++海量数据去重与概率性数据结构

布隆过滤器(Bloom Filter)是一种用于快速判断某个元素是否可能存在于集合中的概率性数据结构。它特别适合处理海量数据去重场景,比如爬虫URL去重、数据库缓存穿透防护等。虽然它会存在一定的误判率(即“假阳性”),但不会出现“假阴性”,而且空间和时间效率极高。

布隆过滤器的核心原理

布隆过滤器由一个长度为 m 的位数组和 k 个独立的哈希函数组成。每个哈希函数将输入元素映射到位数组的一个位置上。

  • 插入元素:对元素使用 k 个哈希函数得到 k 个位置,将位数组中这些位置全部置为 1。
  • 查询元素:同样计算 k 个位置,如果所有位置都为 1,则认为元素“可能存在”;只要有一个位置为 0,就说明元素“一定不存在”。

由于多个元素可能哈希到位数组的相同位置,所以会出现误判——即某个元素没插入过,但它的 k 个位置都被其他元素设为 1,导致判断为“可能存在”。

C++ 实现布隆过滤器的关键步骤

要实现一个高效的布隆过滤器,需要考虑位数组管理、哈希函数设计以及参数调优。

立即学习C++免费学习笔记(深入)”;

1. 使用 bitset 或 vector 管理位数组

为了节省内存,应使用位级别存储。C++ 中推荐使用 std::vector,它是特化的模板,按位存储。

std::vector bits;
size_t size;

2. 设计多个哈希函数

实际中不需要真正实现 k 个完全独立的哈希函数。可以通过一个通用哈希函数结合种子值生成多个不同结果。

常用技巧是使用 std::hash 并引入扰动:

class BloomFilter {
private:
    std::vector bits;
    size_t size;
    size_t hashCount;
// 使用双重哈希生成多个哈希值
std::vector getHashes(const std::string& key) const {
    std::vector hashes;
    std::hash hasher;
    size_t hash1 = hasher(key);
    size_t hash2 = hash1 >> 1;  // 简单扰动生成第二个基础哈希

    for (size_t i = 0; i < hashCount; ++i) {
        hashes.push_back((hash1 + i * hash2) % size);
    }
    return hashes;
}

};

MaxAI
MaxAI

MaxAI.me是一款功能强大的浏览器AI插件,集成了多种AI模型。

下载

3. 插入与查询操作

插入时将所有哈希位置设为 true;查询时检查是否全为 true。

void insert(const std::string& key) {
    auto hashes = getHashes(key);
    for (size_t pos : hashes) {
        bits[pos] = true;
    }
}

bool mayContain(const std::string& key) const { auto hashes = getHashes(key); for (size_t pos : hashes) { if (!bits[pos]) return false; // 一定不存在 } return true; // 可能存在 }

4. 参数选择:m 和 k 的最优值

给定预期插入元素数量 n 和可接受误判率 p,可以推导出最优参数:

  • 位数组长度:m = -n × ln(p) / (ln(2))²
  • 哈希函数数量:k = ln(2) × m / n ≈ 0.693 × m / n

例如,若 n=1000000p=0.01(1%误判率),则 m≈9.6MBk≈7

完整简化版实现示例

#include 
#include 
#include 
#include 
#include 

class BloomFilter { private: std::vector bits; size_t size; size_t hashCount;

std::vector getHashes(const std::string& key) const {
    std::vector hashes;
    std::hash hasher;
    size_t hash1 = hasher(key);
    size_t hash2 = hash1 >> 1;

    for (size_t i = 0; i < hashCount; ++i) {
        hashes.push_back((hash1 + i * hash2) % size);
    }
    return hashes;
}

public: BloomFilter(size_t expectedCount, double errorRate) { // 计算最优 m 和 k double ln2 = std::log(2); size = static_cast(-expectedCount std::log(errorRate) / (ln2 ln2)); hashCount = static_cast(ln2 * size / expectedCount); bits.resize(size, false); }

void insert(const std::string& key) {
    auto hashes = getHashes(key);
    for (size_t pos : hashes) {
        bits[pos] = true;
    }
}

bool mayContain(const std::string& key) const {
    auto hashes = getHashes(key);
    for (size_t pos : hashes) {
        if (!bits[pos]) return false;
    }
    return true;
}

};

// 使用示例 int main() { BloomFilter bf(100000, 0.01); // 支持10万个元素,1%误判率

bf.insert("hello");
bf.insert("world");

std::cout << std::boolalpha;
std::cout << "Contains hello? " << bf.mayContain("hello") << "\n";     // true
std::cout << "Contains foo? " << bf.mayContain("foo") << "\n";         // 可能为 false,也可能误判为 true

return 0;

}

应用场景与注意事项

布隆过滤器非常适合以下场景:

  • 缓存系统中防止缓存穿透(如 Redis + BloomFilter 拦截无效查询)
  • 网页爬虫中判断 URL 是否已抓取
  • 垃圾邮件过滤(邮箱黑名单
  • 大数据去重预处理(先过 BloomFilter 快速筛除已存在项)

需要注意的是:

  • 不支持删除操作(除非使用计数型布隆过滤器 Counting Bloom Filter)
  • 存在误判率,关键业务需配合后端精确查询使用
  • 哈希函数质量影响性能,避免冲突过多

基本上就这些。C++ 实现布隆过滤器不复杂,但对内存和速度要求高的场景下非常实用。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

534

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

194

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

533

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

Redis+MySQL数据库面试教程
Redis+MySQL数据库面试教程

共72课时 | 6.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号