赞
踩
目录
1.学习算法最重要的是理解算法的每一步,而不是记住算法。
2.建议读者学习算法的时候,自己手动一步一步地运行算法。
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能存在于集合中,但可能出现一定的误判率(false positive)。
在C语言中实现布隆过滤器通常包括以下几个关键步骤:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
-
- // 假设我们使用bit数组和几个哈希函数
- #define BITS_PER_FILTER 1 << 24 // 假设我们创建一个24位的布隆过滤器
- #define HASH_FUNCTIONS 5 // 假设我们使用5个独立的哈希函数
-
- // 布隆过滤器结构体定义
- typedef struct {
- unsigned char *bits; // 位数组
- int size; // 位数组大小
- int hash_count; // 哈希函数数量
- } BloomFilter;
-
- // 创建布隆过滤器
- BloomFilter *create_bloom_filter(int expected_elements, double false_positive_rate) {
- int size = (int)(-expected_elements * log(false_positive_rate) / (log(2) * log(2)));
- size = (size + 7) / 8 * 8; // 保证大小为8的倍数
- int optimal_hash_count = (int)(size * log(2) / expected_elements);
-
- BloomFilter *filter = malloc(sizeof(BloomFilter));
- filter->bits = calloc(size, sizeof(unsigned char));
- filter->size = size;
- filter->hash_count = optimal_hash_count > 0 ? optimal_hash_count : HASH_FUNCTIONS;
-
- return filter;
- }
-
- // 使用多个哈希函数计算哈希值并设置位数组
- void bloom_filter_insert(BloomFilter *bf, const char *key) {
- for (int i = 0; i < bf->hash_count; ++i) {
- int hash_val = custom_hash(key, i); // 自定义哈希函数,返回哈希值
- int bit_index = hash_val % bf->size; // 将哈希值映射到位数组的索引
- bf->bits[bit_index / 8] |= (1 << (bit_index % 8)); // 设置位数组相应位置为1
- }
- }
-
- // 判断一个元素是否可能在布隆过滤器中
- bool bloom_filter_maybe_contains(BloomFilter *bf, const char *key) {
- bool maybe_present = true;
- for (int i = 0; i < bf->hash_count && maybe_present; ++i) {
- int hash_val = custom_hash(key, i);
- int bit_index = hash_val % bf->size;
- maybe_present &= (bf->bits[bit_index / 8] & (1 << (bit_index % 8))) != 0; // 如果所有哈希位置均为1,则可能存在于集合中
- }
- return maybe_present;
- }
-
- // 自定义哈希函数,此处仅作示意,实际应用中应使用高质量的哈希函数
- int custom_hash(const char *key, int index) {
- // 此处省略实际哈希函数实现,应确保哈希函数速度快且分布均匀
- return simple_hash_function(key) + index * PRIME_MODIFIER; // 伪代码,实际需要实现稳定的哈希算法
- }
-
- // 释放布隆过滤器资源
- void destroy_bloom_filter(BloomFilter *bf) {
- free(bf->bits);
- free(bf);
- }
-
- // 仅作示意,实际需要实现合适的哈希函数
- int simple_hash_function(const char *key) {
- // 这里只是一个简单的哈希函数示例,实际中应当使用更强大的哈希函数
- int hash = 0;
- while (*key) {
- hash = hash * 31 + *key++;
- }
- return hash % BITS_PER_FILTER;
- }
-
- // 主函数示例
- int main() {
- BloomFilter *bf = create_bloom_filter(1000, 0.01);
- bloom_filter_insert(bf, "apple");
- bloom_filter_insert(bf, "banana");
-
- printf("%s is maybe in the set? %s\n", "apple", bloom_filter_maybe_contains(bf, "apple") ? "yes" : "no");
- printf("%s is maybe in the set? %s\n", "cherry", bloom_filter_maybe_contains(bf, "cherry") ? "yes" : "no");
-
- destroy_bloom_filter(bf);
- return 0;
- }
请注意,上述代码仅作为示例,实际应用中需要实现正确的哈希函数,并且应尽量选择质量高、碰撞少的哈希函数。同时,布隆过滤器的大小、哈希函数数量等参数需要根据预期元素数量和允许的误判率进行调整。在实际C语言程序中,还需要适配实际的哈希函数库。
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,其时空复杂度如下:
布隆过滤器的空间复杂度主要指的是存储元素所需要的位数组大小。假设有m
位的位数组和k
个独立哈希函数,当期望插入n
个元素且达到一定误判率时,布隆过滤器的理想大小(即最小位数组大小)可以通过公式估算得出,一般情况下空间复杂度为O(m)
。实际应用中,m
通常远小于n
,因此布隆过滤器的空间效率很高。
k
次哈希函数并将位数组相应位置设为1,因此插入操作的时间复杂度为O(k)
。k
次哈希函数并检查位数组相应位置,因此查询操作的时间复杂度也为O(k)
。综上所述,布隆过滤器的主要优势在于其空间效率极高,插入和查询操作的时间复杂度较低,均为常数级。然而,代价是存在一定的误判率,即可能出现假阳性(False Positive),但不会出现假阴性(False Negative)。
布隆过滤器(Bloom Filter)是一种空间效率较高的概率型数据结构,用于判断一个元素是否可能存在于集合中。以下是其主要优缺点:
空间效率高:相较于传统的数据结构,如哈希表,布隆过滤器所需的存储空间非常小。特别是对于大型数据集,它可以极大地节省存储资源。
查询速度快:布隆过滤器的查询操作(判断一个元素是否可能存在于集合中)的时间复杂度为常数时间O(k),其中k为哈希函数的个数。
无假阴性:一旦布隆过滤器报告一个元素存在,它必定在集合中(不过要注意这是一个概率声明,存在一定的误判率)。这意味着布隆过滤器不会漏过任何真正的成员,只是可能会将一些非成员误认为成员(假阳性)。
分布式友好:由于布隆过滤器的简洁性,它非常适合在网络中进行传输和在分布式系统中使用。
误报率(False Positives):布隆过滤器最大的缺点是存在一定的误报率,即它可能会错误地报告一个元素存在于集合中,尽管实际上该元素不在。误报率随着存储空间的压缩(即位数组的大小相对于实际元素数量的减小)而增加。
不可删除元素:一旦元素被加入到布隆过滤器中,就不能轻易地从过滤器中删除,因为单个位对应的是多个可能的元素,删除一个元素会导致其他元素的状态发生错误。
无法精确查询:布隆过滤器只能回答“可能在集合中”或“肯定不在集合中”的问题,而不能准确地说出一个元素绝对存在于集合中。
哈希冲突:布隆过滤器的性能严重依赖于所使用的哈希函数的质量。如果哈希函数不够优秀,可能会导致更多冲突和更高的误报率。
因此,布隆过滤器在诸如垃圾邮件过滤、缓存穿透防御、去重等对空间效率要求高且能容忍一定误报率的场景中表现优异。但在需要精确结果的场合下,它不是一个合适的选择。
布隆过滤器(Bloom Filter)在现实中的应用非常广泛,特别是在那些需要高效地判断数据是否存在,且对偶尔的误判有一定容忍度的场景中。以下是一些具体的应用实例:
网页爬虫:
缓存系统:
数据库索引:
垃圾邮件过滤:
实时数据分析:
去重处理:
生物信息学:
社交网络:
广告投放:
总之,布隆过滤器凭借其高效的空间占用和查询速度,在众多需要快速判定数据存在性的场景中发挥了重要作用。尽管它可能会带来一定的误报率,但在合理设计和参数选择下,往往能以较小的成本换取显著的性能提升。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。