C++ 数据结构之布隆过滤器

C++ 数据结构之布隆过滤器

简介

布隆过滤器是一种用于快速判断一个元素是否存在于一个集合中的数据结构。它的空间效率和查询效率都比较高,在某些场景下,它可以代替传统的哈希表。

原理

布隆过滤器的基本原理是:将一个元素映射为多个位数组中的位置。在插入元素时,将这些位置上的值设置为1;在查询元素时,如果这些位置上的值都为1,则认为元素存在于集合中;否则认为元素不存在。(由于哈希函数的不可逆性,可能会出现把不同元素映射到同一位置的情况,因此判断元素不存在是有误差的,但判断元素存在则是准确的)。

为了使误判率尽可能小,布隆过滤器需要用到一个较大的位数组,以及多个不同的哈希函数。一般情况下,哈希函数使用 MurmurHash 或 xxHash 等快速哈希函数即可。

实现

下面介绍一个简单的布隆过滤器的实现。

代码如下:

#include <vector>
#include <cstdlib>
#include <ctime>

class BloomFilter {
public:
    BloomFilter(int n, double p): bit_array_(n), k_(std::log(2) * n / p) {
        srand(time(nullptr));
        for (int i = 0; i < k_; i++) {
            int random_seed = rand();
            hash_seeds_.push_back(random_seed);
        }
    }

    void Add(const std::string& str) {
        for (int i = 0; i < k_; i++) {
            int position = Hash(str, hash_seeds_[i]) % bit_array_.size();
            bit_array_[position] = true;
        }
    }

    bool Query(const std::string& str) const {
        for (int i = 0; i < k_; i++) {
            int position = Hash(str, hash_seeds_[i]) % bit_array_.size();
            if (!bit_array_[position]) {
                return false;
            }
        }
        return true;
    }

private:
    std::vector<bool> bit_array_;
    std::vector<int> hash_seeds_;
    int k_;

    int Hash(const std::string& str, int seed) const {
        unsigned int hash = seed;
        for (int i = 0; i < str.size(); i++) {
            hash = hash * 131 + str[i];
        }
        return hash;
    }
};

这段代码中,我们使用了一个 std::vector<bool> 类型的数组作为位数组,以及一个 std::vector<int> 类型的数组作为哈希种子。

在构造函数中,我们需要指定期望布隆过滤器的大小 n 和误判率 p。根据布隆过滤器的原理,一般情况下需要满足 k = ln(2) * n / p,其中 k 为哈希函数的个数。

随机生成 k 个哈希种子,用来生成 k 个哈希函数。

在插入元素时,通过 k 个哈希函数将元素映射到位数组中。将这些位置上的值设置为 1。

在查询元素时,同样使用 k 个哈希函数将元素映射到位数组中。如果所有位置上的值都为 1,则认为元素存在于集合中;否则认为元素不存在。

示例

下面给出两个使用布隆过滤器的示例。

示例1:URL去重

在爬虫程序中,我们需要对爬取到的每个URL进行去重操作。如果使用一个传统的哈希表来进行去重,需要使用大量的内存来存储这些URL,而且查询速度会较慢。布隆过滤器可以帮助我们在较小的空间和较快的查询速度之间取得平衡。

int main() {
    BloomFilter filter(1000000, 0.001);
    std::string url1 = "https://www.baidu.com";
    std::string url2 = "https://www.baidu.com";
    filter.Add(url1);
    if (filter.Query(url2)) {
        std::cout << "URL already exists." << std::endl;
    } else {
        std::cout << "URL does not exist." << std::endl;
    }
    return 0;
}

在上面的示例中,我们创建了一个布隆过滤器,指定了 1000000 的大小,以及 0.001 的误判率。然后向过滤器中插入了一个名字相同的 URL,并且查询了另一个名字相同的 URL。

示例2:IP黑名单过滤

在网络应用中,我们需要对一些IP地址进行黑名单过滤,防止这些IP地址发起攻击。布隆过滤器可以帮助我们在较小的内存和较快的查询速度之间取得平衡。

int main() {
    BloomFilter filter(1000000, 0.001);
    std::string ip1 = "192.168.0.1";
    std::string ip2 = "192.168.0.2";
    filter.Add(ip1);
    if (filter.Query(ip2)) {
        std::cout << "IP is in blacklist." << std::endl;
    } else {
        std::cout << "IP is not in blacklist." << std::endl;
    }
    return 0;
}

在上面的示例中,我们创建了一个布隆过滤器,指定了 1000000 的大小,以及 0.001 的误判率。然后向过滤器中插入了一个 IP 地址,并且查询了另一个 IP 地址,看它是否在黑名单中。

总结

布隆过滤器是一种空间效率和查询效率都比较高的数据结构,常用于集合判重、黑名单过滤等场景中。使用布隆过滤器需要注意一些参数的设置,以及哈希函数的选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 数据结构之布隆过滤器 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 常用的Java数据结构知识点汇总

    常用的Java数据结构知识点汇总 简介 Java中的数据结构是Java程序开发中非常重要的一部分。掌握常用的数据结构知识点是编写高效、优秀的Java程序的关键之一。本文将详细讲解Java中常用的数据结构知识点,并提供代码示例说明。 数组(Array) 数组是一组相同类型的数据集合,通过数组下标来访问数据,数组长度确定后就无法改变。在Java中,数组可以是基本…

    数据结构 2023年5月17日
    00
  • C#数据结构之队列(Quene)实例详解

    C#数据结构之队列(Quene)实例详解 什么是队列? 队列是一种线性数据结构,只允许在队列的两端进行操作。队列是一种FIFO(First in First Out)的数据结构,即先进先出,类似于排队买票的场景。 C#中的队列(Quene) C#中队列(Quene)是System.Collections命名空间中的一个类,可以通过引入System.Colle…

    数据结构 2023年5月17日
    00
  • 【牛客小白月赛70】A-F题解【小d和超级泡泡堂】【小d和孤独的区间】【小d的博弈】【小d和送外卖】

    比赛传送门:https://ac.nowcoder.com/acm/contest/53366 难度适中。 ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 阅读原文获得更好阅读体验:https://www.erikt…

    算法与数据结构 2023年4月17日
    00
  • MySQL索引背后的数据结构及算法原理详解

    《MySQL索引背后的数据结构及算法原理详解》是一篇介绍MySQL索引背后的数据结构和算法原理的文章。MySQL索引是提高查询效率的一个重要工具,理解其背后的数据结构和算法原理对于提高数据库性能和优化查询操作是非常有帮助的。 本文主要分为以下三部分: MySQL索引背后的数据结构 索引的几种常见数据结构及其优缺点 索引的算法原理 MySQL索引背后的数据结构…

    数据结构 2023年5月17日
    00
  • C++数据结构二叉搜索树的实现应用与分析

    C++数据结构二叉搜索树的实现应用与分析 什么是二叉搜索树? 二叉搜索树(Binary Search Tree,BST),也称二叉查找树、二叉排序树,它是一种特殊的二叉树。对于每个节点,其左子树上所有节点的值均小于等于该节点的值,右子树上所有节点的值均大于等于该节点的值。通过这种特殊的结构,二叉搜索树能够帮助我们快速地执行查找、插入、删除等操作。 如何实现二…

    数据结构 2023年5月17日
    00
  • C++数据结构与算法的基础知识和经典算法汇总

    C++数据结构与算法的基础知识和经典算法汇总 1. 基础知识 1.1 数据结构 数据结构是计算机存储、组织数据的方式。这里列出常见的数据结构,包括但不限于: 数组 链表 栈 队列 树 哈希表 1.2 算法 算法是解决问题的步骤和方法。下列是常见的算法: 排序算法 查找算法 字符串算法 图算法 1.3 复杂度 复杂度是算法性能的度量。常见的复杂度表示法有O(n…

    数据结构 2023年5月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • C++数据结构AVL树全面分析

    C++数据结构AVL树全面分析 简介 AVL树是一种二叉搜索树,它通过使树保持高度平衡来提高搜索、插入和删除操作的效率。AVL树本质上是通过在插入和删除节点时旋转子树来保持平衡的。AVL树被认为是最早的自平衡二元搜索树。 AVL树的定义 AVL树是一种满足以下特性的BST: 每个节点都有一个左子树和一个右子树,并且左子树、右子树也是AVL树。 左子树高度和右…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部