1. 位图 (Bitmap / Bitset)
1.1 介绍
位图是一种极其节省空间的数据结构,用于高效地表示和操作大量布尔值(通常是存在或不存在)。其核心思想是:用一个比特位(bit)来标记一个元素的状态(通常是存在与否)。
- 优点:
- 空间效率极高: 存储 N 个元素的状态只需要大约 $N/8$ 个字节的内存。
- 查询和修改速度快: 位运算(与、或、非、异或等)是 CPU 直接支持的基础操作,速度极快。
- 缺点:
- 只能表示整数状态: 通常只能表示一个元素是否存在(或最多几种有限状态,如果扩展到多位)。
- 范围有限: 需要预先确定要表示的元素范围(最大值),如果元素值范围非常大但实际元素稀疏,空间浪费可能仍然存在。
- 应用场景:
- 快速查找一个数字是否在一个大集合中出现过(例如,40亿个整数中查找一个数)。
- 排序(遍历位图即可得到排序结果)。
- 数据去重。
- 操作系统的磁盘块管理、内存页管理。
1.2 C++ 实现
C++ 标准库提供了 std::bitset,但这里我们实现一个简化版以理解原理。
class Bitmap {
public:
explicit Bitmap(size_t max_value) {
// 计算需要的 char 数量,每个 char 有 8 位
size_t num_chars = (max_value + 7) / 8; // +7 确保向上取整
_bits.resize(num_chars, 0);
}
// 设置第 n 位为 1
void set(size_t n) {
size_t index = n / 8; // 找到在哪个 char 里
size_t offset = n % 8; // 找到在 char 中的哪一位
_bits[index] |= (1 << offset); // 使用位或操作设置该位
}
// 设置第 n 位为 0
void reset(size_t n) {
size_t index = n / 8;
size_t offset = n % 8;
_bits[index] &= ~(1 << offset); // 使用位与和取反操作清除该位
}
// 检查第 n 位是否为 1
bool test(size_t n) const {
size_t index = n / 8;
size_t offset = n % 8;
return (_bits[index] & (1 << offset)) != 0; // 使用位与操作检查该位
}
private:
std::vector<unsigned char> _bits; // 使用 unsigned char 数组存储比特位
};
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUzNi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUzNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDM1Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI4MC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDM0Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUyMi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI3MS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI2OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDMyNy5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDE5Ni5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI1MC5zaHRtbA==.html
http://my.tv.sohu.com/us/441720479/694374536.shtml
http://my.tv.sohu.com/us/441720479/694374534.shtml
http://my.tv.sohu.com/us/441720479/694374352.shtml
http://my.tv.sohu.com/us/441720479/694374283.shtml
http://my.tv.sohu.com/us/441720479/694374280.shtml
http://my.tv.sohu.com/us/441720479/694374342.shtml
http://my.tv.sohu.com/us/441720479/694374522.shtml
http://my.tv.sohu.com/us/441720479/694374271.shtml
http://my.tv.sohu.com/us/441720479/694374268.shtml
http://my.tv.sohu.com/us/441720479/694374327.shtml
http://my.tv.sohu.com/us/441720479/694374196.shtml
http://my.tv.sohu.com/us/441720479/694374250.shtml
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDcyMi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDU2My5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDM3OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDcwNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDYyMS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDYxOC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDU0Ny5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDQ5NS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDUwNi5zaHRtbA==.html
http://my.tv.sohu.com/us/440305028/694374722.shtml
http://my.tv.sohu.com/us/440305028/694374629.shtml
http://my.tv.sohu.com/us/440305028/694374563.shtml
http://my.tv.sohu.com/us/440305028/694374378.shtml
http://my.tv.sohu.com/us/440305028/694374704.shtml
http://my.tv.sohu.com/us/440305028/694374621.shtml
http://my.tv.sohu.com/us/440305028/694374618.shtml
http://my.tv.sohu.com/us/440305028/694374495.shtml
http://my.tv.sohu.com/us/440305028/694374506.shtml
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY3OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDgyNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU5Ny5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU5Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDgwNy5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY1Ni5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY1Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU3Ny5zaHRtbA==.html
http://my.tv.sohu.com/us/441643934/694374678.shtml
http://my.tv.sohu.com/us/441643934/694374824.shtml
http://my.tv.sohu.com/us/441643934/694374597.shtml
http://my.tv.sohu.com/us/441643934/694374592.shtml
http://my.tv.sohu.com/us/441643934/694374807.shtml
http://my.tv.sohu.com/us/441643934/694374656.shtml
http://my.tv.sohu.com/us/441643934/694374652.shtml
http://my.tv.sohu.com/us/441643934/694374577.shtml
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDk0My5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDg2MS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDkyOS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDkyNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDgzOC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDgzMy5zaHRtbA==.html
http://my.tv.sohu.com/us/438920216/694374943.shtml
http://my.tv.sohu.com/us/438920216/694374861.shtml
http://my.tv.sohu.com/us/438920216/694374929.shtml
http://my.tv.sohu.com/us/438920216/694374924.shtml
http://my.tv.sohu.com/us/438920216/694374838.shtml
http://my.tv.sohu.com/us/438920216/694374833.shtml
2. 布隆过滤器 (Bloom Filter)
2.1 介绍
布隆过滤器是位图的一种扩展,用于高效地判断一个元素是否“可能存在于”一个集合中,或者“一定不存在于”集合中。它牺牲了确定性(可能存在误判),换来了更高的空间效率和插入/查询速度。
-
核心思想:
- 使用一个大的位数组(位图)。
- 使用 $k$ 个不同的哈希函数。
- 插入元素:将元素分别用 $k$ 个哈希函数计算出 $k$ 个哈希值(对应位数组中的 $k$ 个位置),然后将这 $k$ 个位置都设置为 1。
- 查询元素:用同样的 $k$ 个哈希函数计算元素的 $k$ 个位置。如果这 $k$ 个位置都为 1,则认为元素“可能存在”;如果其中任何一个位置为 0,则元素“一定不存在”。
-
优点:
- 空间效率极高: 远低于存储原始数据或使用哈希表。
- 插入和查询速度快: 只涉及常数次(k 次)哈希计算和位操作。
-
缺点:
- 存在误判率: 可能将不存在的元素误判为存在(False Positive)。但绝不会将存在的元素误判为不存在(False Negative)。
- 无法删除元素: 因为多个元素可能共享同一个比特位。强行删除会影响其他元素的判断。有支持删除的变种(Counting Bloom Filter),但需要更多空间。
-
应用场景:
- 缓存穿透保护(如 Redis 前的屏障)。
- 垃圾邮件过滤。
- 爬虫 URL 去重。
- 数据库查询优化(判断某个键一定不存在)。
- 分布式系统中判断元素是否存在于远程集合。
2.2 误判率分析
误判率 $p$ 与位数组大小 $m$、插入元素数量 $n$、哈希函数数量 $k$ 有关。近似公式为: $$ p \\approx (1 – e^{-kn/m})^k $$
2.3 C++ 实现
#include <vector>
#include <functional> // std::hash
class BloomFilter {
public:
BloomFilter(size_t expected_size, double false_positive_prob)
: _bit_size(static_cast<size_t>(-expected_size * std::log(false_positive_prob) / (std::log(2) * std::log(2)))),
_hash_num(static_cast<size_t>(std::log(2) * _bit_size / expected_size)) {
// 根据预期元素数量和误判率计算位图大小和哈希函数个数
_bits.resize((_bit_size + 7) / 8, 0); // 向上取整计算字节数
}
void add(const std::string& key) {
for (size_t i = 0; i < _hash_num; ++i) {
size_t hash_val = hash_i(key, i) % _bit_size;
size_t index = hash_val / 8;
size_t offset = hash_val % 8;
_bits[index] |= (1 << offset);
}
}
bool contains(const std::string& key) const {
for (size_t i = 0; i < _hash_num; ++i) {
size_t hash_val = hash_i(key, i) % _bit_size;
size_t index = hash_val / 8;
size_t offset = hash_val % 8;
if ((_bits[index] & (1 << offset)) == 0) {
return false; // 只要有一位是0,肯定不存在
}
}
return true; // 所有位都是1,可能存在(存在误判)
}
private:
std::vector<unsigned char> _bits;
size_t _bit_size; // 位数组的总比特数
size_t _hash_num; // 哈希函数的数量
// 模拟第 i 个哈希函数 (实际应用中应选择不同的优质哈希函数)
size_t hash_i(const std::string& key, size_t i) const {
// 示例:使用 std::hash 加种子偏移模拟不同哈希函数
// 实际应使用如 MurmurHash, FNV 等,或独立参数
return std::hash<std::string>{}(key + std::to_string(i));
}
};
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUzNi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUzNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDM1Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI4MC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDM0Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDUyMi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI3MS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI2OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDMyNy5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDE5Ni5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNzIwNDc5LzY5NDM3NDI1MC5zaHRtbA==.html
http://my.tv.sohu.com/us/441720479/694374536.shtml
http://my.tv.sohu.com/us/441720479/694374534.shtml
http://my.tv.sohu.com/us/441720479/694374352.shtml
http://my.tv.sohu.com/us/441720479/694374283.shtml
http://my.tv.sohu.com/us/441720479/694374280.shtml
http://my.tv.sohu.com/us/441720479/694374342.shtml
http://my.tv.sohu.com/us/441720479/694374522.shtml
http://my.tv.sohu.com/us/441720479/694374271.shtml
http://my.tv.sohu.com/us/441720479/694374268.shtml
http://my.tv.sohu.com/us/441720479/694374327.shtml
http://my.tv.sohu.com/us/441720479/694374196.shtml
http://my.tv.sohu.com/us/441720479/694374250.shtml
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDcyMi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDU2My5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDM3OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDcwNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDYyMS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDYxOC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDU0Ny5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDQ5NS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQwMzA1MDI4LzY5NDM3NDUwNi5zaHRtbA==.html
http://my.tv.sohu.com/us/440305028/694374722.shtml
http://my.tv.sohu.com/us/440305028/694374629.shtml
http://my.tv.sohu.com/us/440305028/694374563.shtml
http://my.tv.sohu.com/us/440305028/694374378.shtml
http://my.tv.sohu.com/us/440305028/694374704.shtml
http://my.tv.sohu.com/us/440305028/694374621.shtml
http://my.tv.sohu.com/us/440305028/694374618.shtml
http://my.tv.sohu.com/us/440305028/694374495.shtml
http://my.tv.sohu.com/us/440305028/694374506.shtml
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY3OC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDgyNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU5Ny5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU5Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDgwNy5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY1Ni5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDY1Mi5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDQxNjQzOTM0LzY5NDM3NDU3Ny5zaHRtbA==.html
http://my.tv.sohu.com/us/441643934/694374678.shtml
http://my.tv.sohu.com/us/441643934/694374824.shtml
http://my.tv.sohu.com/us/441643934/694374597.shtml
http://my.tv.sohu.com/us/441643934/694374592.shtml
http://my.tv.sohu.com/us/441643934/694374807.shtml
http://my.tv.sohu.com/us/441643934/694374656.shtml
http://my.tv.sohu.com/us/441643934/694374652.shtml
http://my.tv.sohu.com/us/441643934/694374577.shtml
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDk0My5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDg2MS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDkyOS5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDkyNC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDgzOC5zaHRtbA==.html
https://tv.sohu.com/v/dXMvNDM4OTIwMjE2LzY5NDM3NDgzMy5zaHRtbA==.html
http://my.tv.sohu.com/us/438920216/694374943.shtml
http://my.tv.sohu.com/us/438920216/694374861.shtml
http://my.tv.sohu.com/us/438920216/694374929.shtml
http://my.tv.sohu.com/us/438920216/694374924.shtml
http://my.tv.sohu.com/us/438920216/694374838.shtml
http://my.tv.sohu.com/us/438920216/694374833.shtml
3. 总结
- 位图: 精确表示整数集合的存在性,空间效率极高,操作极快。
- 布隆过滤器: 概率性地判断任意类型元素的存在性(可能有误判),空间效率比哈希表高得多,插入查询速度也很快。牺牲确定性换取空间和速度。 两者都是处理海量数据、空间敏感问题的利器,根据具体需求(是否需要精确性、元素类型、是否支持删除)选择合适的数据结构。
网硕互联帮助中心







评论前必须登录!
注册