数据结构 布隆过滤器

头文件

cpp 复制代码
#include <stdint.h>
#include <stddef.h>

// 布隆过滤器结构
typedef struct BloomFilter {
    uint8_t* bit_array;      // 位数组
    size_t bit_array_size;   // 位数组大小(字节数)
    size_t num_bits;         // 总位数
    int num_hash_funcs;      // 哈希函数数量
    size_t element_count;    // 已插入元素数量
} BloomFilter;

// API 函数
// 创建布隆过滤器
BloomFilter* bloom_filter_create(size_t num_bits, int num_hash_funcs);
//销毁
void bloom_filter_destroy(BloomFilter* filter);
//添加元素
int bloom_filter_add(BloomFilter* filter, const char* element);
//检查元素是否存在
int bloom_filter_contains(const BloomFilter* filter, const char* element);
//获得已插入元素数量
size_t bloom_filter_size(const BloomFilter* filter);
//清空
void bloom_filter_clear(BloomFilter* filter);
//计算理论误判率
double bloom_filter_false_positive_rate(const BloomFilter* filter);

源文件

cpp 复制代码
#include "布隆过滤器.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>

// 哈希函数1:DJB2
static uint32_t hash1(const char* str) {
    uint32_t hash = 5381;
    int c;
    while ((c = *str++)) {
        hash = ((hash << 5) + hash) + c; // hash * 33 + c
    }
    return hash;
}

// 哈希函数2:FNV-1a
static uint32_t hash2(const char* str) {
    uint32_t hash = 2166136261u;
    while (*str) {
        hash ^= (uint8_t)(*str);
        hash *= 16777619u;
        str++;
    }
    return hash;
}
// 双哈希法生成第i个哈希值
static uint32_t get_hash(const BloomFilter* filter, const char* str, int i) {
    uint32_t h1 = hash1(str);
    uint32_t h2 = hash2(str);
    return (h1 + i * h2) % filter->num_bits;
}
// 创建布隆过滤器
BloomFilter* bloom_filter_create(size_t num_bits, int num_hash_funcs) {
    if (num_bits == 0 || num_hash_funcs <= 0) {
        return NULL;
    }
    BloomFilter* filter = (BloomFilter*)malloc(sizeof(BloomFilter));
    if (!filter) return NULL;
    // 计算需要的字节数(向上取整)
    size_t byte_size = (num_bits + 7) / 8;
    filter->bit_array = (uint8_t*)calloc(byte_size, sizeof(uint8_t));
    if (!filter->bit_array) {
        free(filter);
        return NULL;
    }
    filter->bit_array_size = byte_size;
    filter->num_bits = num_bits;
    filter->num_hash_funcs = num_hash_funcs;
    filter->element_count = 0;
    return filter;
}

// 销毁布隆过滤器
void bloom_filter_destroy(BloomFilter* filter) {
    if (filter) {
        if (filter->bit_array) {
            free(filter->bit_array);
        }
        free(filter);
    }
}

// 添加元素
int bloom_filter_add(BloomFilter* filter, const char* element) {
    if (!filter || !element) return 0;
    size_t len = strlen(element);
    if (len == 0) return 0;
    for (int i = 0; i < filter->num_hash_funcs; i++) {
        uint32_t hash = get_hash(filter, element, i);
        size_t byte_index = hash / 8;
        uint8_t bit_offset = hash % 8;
        // 设置位
        filter->bit_array[byte_index] |= (1 << bit_offset);
    }
    filter->element_count++;
    return 1;
}

// 检查元素是否存在
int bloom_filter_contains(const BloomFilter* filter, const char* element) {
    if (!filter || !element) return 0;
    size_t len = strlen(element);
    if (len == 0) return 0;
    for (int i = 0; i < filter->num_hash_funcs; i++) {
        uint32_t hash = get_hash(filter, element, i);
        size_t byte_index = hash / 8;
        uint8_t bit_offset = hash % 8;
        // 检查位是否被设置
        if (!(filter->bit_array[byte_index] & (1 << bit_offset))) {
            return 0; // 肯定不存在
        }
    }
    return 1; // 可能存在(可能误判)
}

// 获取已插入元素数量
size_t bloom_filter_size(const BloomFilter* filter) {
    return filter ? filter->element_count : 0;
}

// 清空布隆过滤器
void bloom_filter_clear(BloomFilter* filter) {
    if (filter && filter->bit_array) {
        memset(filter->bit_array, 0, filter->bit_array_size);
        filter->element_count = 0;
    }
}

// 计算理论误判率
double bloom_filter_false_positive_rate(const BloomFilter* filter) {
    if (!filter || filter->element_count == 0) return 0.0;
    // 误判率公式: (1 - e^(-k * n / m))^k
    double k = filter->num_hash_funcs;
    double m = filter->num_bits;
    double n = filter->element_count;
    double exponent = -k * n / m;
    return pow(1 - exp(exponent), k);
}
相关推荐
咕叽吧咔1 天前
LeetBook乐扣题库 142. 环形链表 II
java·数据结构·leetcode·链表
郝学胜-神的一滴1 天前
贪心策略实战Leetcode 860题:柠檬水找零问题的优雅解法
数据结构·c++·算法·leetcode·职场和发展
季明洵1 天前
预处理详解(上)
linux·c语言·数据结构·预定义
handler011 天前
算法:字符串哈希
c语言·数据结构·c++·笔记·算法·哈希算法·散列表
handler011 天前
算法:查并集
开发语言·数据结构·c++·笔记·学习·算法·c
雨落在了我的手上1 天前
C语言之数据结构初见篇(5):单链表的介绍(1)
c语言·开发语言·数据结构
易雪寒1 天前
Java List 根据List中对象的属性值是否相同作为同一组,分割成多个连续的子List
java·数据结构·list·分组切割
Book思议-1 天前
【数据结构实战】单向循环单链表判别条件理解
c语言·数据结构·算法
Book思议-1 天前
【数据结构实战】双向链表头插法
c语言·数据结构·链表
weixin_458872611 天前
东华复试OJ二刷复盘13
数据结构·算法