【C++】:位图(bitset)

目录

位图的概念

位图的应用场景

位图的构造函数

位图的使用

 


位图的概念

位图(Bitmap)是一种基于二进制位(bit)的高效数据结构,用于表示一组布尔值(存在或不存在、真或假)。它的核心思想是:用每一个二进制位(0或1)来标记某个状态或资源是否被占用

  • 第 i 位为 1 → 表示第 i 个元素存在/被占用。

  • 第 i 位为 0 → 表示第 i 个元素不存在/未被占用。

关键特性:

  1. 内存高效
    每个布尔值仅占用 1 个二进制位(bit),而非传统布尔变量(通常占用 1 字节)。例如:

    • 存储 1000 个布尔值:

      • 传统布尔数组:1000 字节(1 字节/布尔值)。

      • 位图:仅需 1000 / 8 = 125 字节。

  2. 快速操作
    通过位运算(如 ANDOR移位)快速完成批量操作(如批量标记、清除、查询)。

  3. 连续存储
    位图数据通常以连续内存块(如数组或 std::bitset)存储,适合高效缓存访问。

位图的应用场景

适用场景

1. 资源管理

  • 内存分配:操作系统用位图跟踪物理内存页的占用情况(例如,Linux 的 mem_map)。

  • 文件系统块管理:标记磁盘块是否已被文件占用。

  • 线程池任务分配:标记哪些任务槽位空闲或忙碌。

2. 集合运算与过滤

  • 布隆过滤器(Bloom Filter)
    位图是布隆过滤器的核心组件,用于快速判断元素是否可能存在于集合中(允许误报,但绝不漏报)。

  • 交集/并集运算
    通过位图的 AND/OR 操作,快速计算两个集合的交集或并集。

3. 压缩存储

  • 稀疏数据标记
    例如标记用户是否完成某个任务(1亿用户仅需 100,000,000 / 8 ≈ 12 MB)。

  • 图像二值化处理
    黑白图像中每个像素用 1 位表示(0=黑,1=白)。

4. 高效查询场景

  • 数据库索引
    位图索引(Bitmap Index)用于快速查询特定属性的记录(如性别=“男”)。

  • 网络连接状态
    跟踪大量 TCP 连接是否活跃(如每秒处理百万级连接)。

5. 算法优化

  • 埃拉托斯特尼筛法(素数筛选)
    用位图标记数字是否为素数。

  • 状态压缩
    在动态规划或回溯算法中,用位图压缩存储状态(如 N 皇后问题中标记列、对角线的占用)。

位图的构造函数

1. 默认构造函数

#include 
std::bitset<8> bits;  // 8 位位图,所有位初始化为 0

2. 通过整数初始化 

std::bitset<8> bits1(0b10101010);  // 二进制字面量初始化
std::bitset<8> bits2(255);         // 十进制整数初始化(255 = 0b11111111)

3. 通过字符串初始化

用 0 和 1 组成的字符串初始化位图:

// 从字符串构造,可指定起始位置和长度
std::bitset<8> bits3("10101010");          // 直接初始化
std::bitset<8> bits4("11110000", 4);       // 取前4位 "1111",高位补0 → 00001111
std::bitset<8> bits5("AB1010CD", 2, 4);    // 从索引2开始取4个字符 "1010" → 00001010

注意:如果字符串包含非 0/1 字符或数值超出范围,会抛出 std::invalid_argument 异常。 

位图的使用

位图中常用的成员函数如下:

函数名称 作用 示例
set() 设置指定位为 1
- 无参数:设置所有位为 1
- 有参数:设置指定索引的位为 1
bits.set();
bits.set(3);
reset() 清除指定位为 0
- 无参数:清除所有位
- 有参数:清除指定索引的位。
bits.reset();
bits.reset(2);
test(size_t pos) 检查指定索引位的值(返回 bool)。
注意:越界会抛出 std::out_of_range 异常。
if (bits.test(3)) { ... }
flip() 翻转位的值:
- 无参数:翻转所有位
- 有参数:翻转指定索引的位。
bits.flip();
bits.flip(4);
size() 返回位图的总位数(编译时确定的值)。 size_t n = bits.size(); // 8
count() 返回当前设置为 1 的位的数量。 int ones = bits.count();
all() 检查是否所有位都为 1(C++11 起支持)。 if (bits.all()) { ... }
any() 检查是否至少有一位为 1 if (bits.any()) { ... }
none() 检查是否所有位都为 0 if (bits.none()) { ... }
to_ulong() 将位图转换为 unsigned long 整数(超出范围时抛出 std::overflow_error)。 unsigned long val = bits.to_ulong();
to_ullong() 将位图转换为 unsigned long long 整数(C++11 起支持)。 auto val = bits.to_ullong();
to_string() 将位图转换为 0/1 字符串(可指定填充字符)。 std::string s = bits.to_string('_', 'X');

 代码示例:

#include 
#include 

int main() 
{
    std::bitset<8> bits("11001100");
    bits.set(0);            // 设置第0位 → 11001101
    bits.flip(3);           // 翻转第3位 → 11000101
    std::cout << "Bits: " << bits << std::endl;             // 输出 11000101
    std::cout << "Count: " << bits.count() << std::endl;    // 输出 4
    std::cout << "Value: " << bits.to_ulong() << std::endl; // 输出 197
    return 0;
}
operator[] 访问指定索引的位:
- 非 const 版本返回代理对象,允许修改
- 不检查越界。
bits[2] = true;
bool b = bits[3];
operator<</operator>> 左移或右移位图(返回新位图,原数据不变)。 auto shifted = bits << 2;
位图之间的按位与、或、异或操作(需大小相同)。 auto result = bits1 & bits2;
operator~ 按位取反,返回新位图。 auto inverted = ~bits;
hash() 返回位图的哈希值(C++11 起支持,用于 std::unordered_set 等容器)。 size_t h = std::hash>()(bits);

 代码示例:

#include 
#include 
#include 
using namespace std;

int main()
{
	bitset<8> bs1(string("10101010"));
	bitset<8> bs2(string("10101010"));
	bs1 >>= 1;
	cout << bs1 << endl; //01010101

	bs2 |= bs1;
	cout << bs2 << endl; //11111111
	return 0;
}


 

你可能感兴趣的:(重制C++版,c++,开发语言,c语言,数据结构,算法)