bitmap算法用位映射实现十亿整数去重,仅需约119mb内存;通过new uchar[]申请连续内存、memset清零,并手动计算字节索引与位偏移进行set/test/reset操作。

用C++实现Bitmap算法处理十亿级整数去重,必须在内存受限(如仅1GB RAM)下完成——传统std::set会因指针开销和动态分配直接OOM,而Bitmap将每个整数映射为1位,理论空间压缩率达99.999%以上。
基础Bitmap结构设计与内存对齐初始化
第一步:确定数据范围。若所有整数∈[0, 2³²),则需2³²位 = 512MB连续内存;若实际范围是[0, 10⁹),则只需10⁹/8 ≈ 119MB,【务必先统计min/max,切勿盲目按UINT_MAX分配】。
第二步:使用new unsigned char[]而非vector
第三步:调用memset(ptr, 0, size)清零,不使用for循环逐字节赋值——现代glibc的memset针对大块内存做了SIMD优化,速度提升3~5倍。
位操作核心函数:set、test、reset
方法一:手动计算字节索引与位偏移
index = num / 8 → byte_pos = index, bit_pos = num % 8 → 使用bitmask (1U
方法二:利用GCC内置函数__builtin_clzll(需64位环境)加速bitmask生成——当num较小时,(1ULL 【num必须严格小于64,否则行为未定义】。
方法三:预生成256字节查找表(LUT),table[value]返回对应bitmask。适用于嵌入式或缓存敏感场景,但x86-64下L1d cache仅32KB,查表反而可能增加cache miss。
空间开销二次压缩:Roaring Bitmap逻辑集成
当输入数据呈现局部聚集性(如IP地址段、时间戳序列),纯Bitmap大量连续0/1造成浪费。此时将Bitmap切分为65536个container(每container覆盖65536个整数),对每个container:
① 若set bit数 ② 若set bit数 ≥ 4096且分布稀疏,用BitmapContainer(即原生Bitmap);
③ 若全满或接近全满,用RunContainer(存储起始值+长度对)。
这一步必须在构造完成后立即执行recompress(),否则后续add操作仍走原始Bitmap路径,【错过压缩时机将永久失去空间优势】。
并发安全的批量插入与快速存在性查找
使用std::atomic
对10⁹量级数据做存在性查询,优先构建布隆过滤器(Bloom Filter)作前置过滤:误判率设为0.01时仅需1.44×n×ln(1/ε)≈1.9GB位数组,但能拦截99%的不存在查询,使真实Bitmap访问频次下降两个数量级。
最后,将Bitmap内存mmap到/dev/shm(Linux共享内存),进程重启后可直接复用已构建结构,避免重复加载耗时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











