在处理海量数据时,我们常常需要快速判断一个元素是否存在于一个集合中。例如:防止缓存穿透、垃圾邮件过滤、URL去重等场景。这时,C语言布隆过滤器(Bloom Filter)就派上了用场!
布隆过滤器是一种空间效率极高的概率型数据结构,由 Burton Howard Bloom 在 1970 年提出。它能以极小的内存开销,快速判断“某个元素一定不存在”或“可能存在”。注意:它允许一定的误判率,但不会漏判。
布隆过滤器由一个位数组(bit array)和多个独立的哈希函数组成:
下面是一个简化但完整的 C语言布隆过滤器实现,适合初学者理解。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#define BIT_SET(a, n) ((a)[(n)/8] |= (1 << ((n) % 8)))#define BIT_TEST(a, n) ((a)[(n)/8] & (1 << ((n) % 8)))// 简单的哈希函数(实际应用中建议使用更好的哈希,如 MurmurHash)unsigned int hash2(const char *str) { unsigned int hash = 0; while (*str) { hash = hash * 31 + *str++; } return hash;}unsigned int hash2(const char *str) { unsigned int hash = 5381; while (*str) { hash = ((hash << 5) + hash) + *str++; } return hash;}// 布隆过滤器结构体typedef struct { uint8_t *bits; // 位数组 size_t size; // 位数组大小(单位:bit)} BloomFilter;// 初始化布隆过滤器BloomFilter* bloom_init(size_t bit_size) { BloomFilter *bf = (BloomFilter*)malloc(sizeof(BloomFilter)); bf->size = bit_size; bf->bits = (uint8_t*)calloc((bit_size + 7) / 8, sizeof(uint8_t)); return bf;}// 添加元素void bloom_add(BloomFilter *bf, const char *item) { unsigned int h2 = hash2(item) % bf->size; unsigned int h2 = hash2(item) % bf->size; BIT_SET(bf->bits, h2); BIT_SET(bf->bits, h2);}// 查询元素是否存在int bloom_test(BloomFilter *bf, const char *item) { unsigned int h2 = hash2(item) % bf->size; unsigned int h2 = hash2(item) % bf->size; if (BIT_TEST(bf->bits, h2) && BIT_TEST(bf->bits, h2)) { return 1; // 可能存在 } return 0; // 一定不存在}// 释放内存void bloom_free(BloomFilter *bf) { free(bf->bits); free(bf);}// 测试示例int main() { BloomFilter *bf = bloom_init(1000); // 1000 bits bloom_add(bf, "apple"); bloom_add(bf, "banana"); printf("'apple' exists? %s\n", bloom_test(bf, "apple") ? "Yes" : "No"); printf("'orange' exists? %s\n", bloom_test(bf, "orange") ? "Yes" : "No"); bloom_free(bf); return 0;} BIT_SET 和 BIT_TEST 用于高效操作单个 bit。假设你要存储 n 个元素,可接受误判率为 p,则:
m = - (n * ln p) / (ln 2)²k = (m / n) * ln 2例如:n=10000, p=1%,则 m≈95851 bits(约11.7KB),k≈7。
适用场景(高效去重算法):
不适用场景:
通过本文,你已经掌握了 C语言布隆过滤器 的基本原理、实现方法和使用场景。虽然它有误判率,但在许多高效去重算法需求中,它以极小的空间代价换来了极高的查询效率,是值得掌握的C语言数据结构技巧。
动手试试吧!你可以将上述代码编译运行,并尝试添加更多哈希函数或优化内存管理,深入理解这一经典数据结构的魅力。
本文由主机测评网于2025-12-23发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/20251211901.html