用基于范围的for循环遍历bitset的所有有效位置

本文介绍如何在没有SGI版本std::bitset的_Find_First和_Find_Next接口时,利用位运算性质实现对bitset的有效位置进行遍历。通过FindFirst和FindNext函数,结合std::bitset的内部结构,构建迭代器并重载必要的操作符,最终实现基于范围的for循环遍历bitset。
摘要由CSDN通过智能技术生成

标准库中的std::bitset,利用若干个uint32_t或者uint64_t作为存储单元,来表示多个位置的0-1状态,可以节约很多的空间。例如,有31组开关,最少可以只用一个uint32_t来存储这31组开关的状态,只占用4个字节。

现在的需求是,对于这31组开关,依次找到其中打开的,做一系列的处理。标准的std::bitset并没有提供遍历的接口。

在SGI版本的实现中,std::bitset有_Find_First()和_Find_Next()的接口,可以通过如下代码遍历:

std::bitset<31> bs{};
...
for(size_t pos = bs._Find_First(); pos < bs.size(); pos = bs._Find_Next(pos)){
    ...
}

但这两个接口不是std::bitset必须实现的,visual studio版本并没有这个接口,并且,上述书写方式也比较繁琐,容易出错,用range-based for会更加清爽。

对于非SGI版本,首先要实现FindFirst和FindNext。FindFirst本质就是寻找一个数最低位1的位置,而FindNext则是屏蔽掉当前位置之前的所有1,再做FindFirst操作。

这里我们可以利用一个位运算的性质:对于一个数n,n & (-n) 即可屏蔽掉除最低位的1以外的所有1。因为-n即n取反再加1,所以比最低位1高的位置,因为取反再取与,会变成0;比最低位1低的位置,必然全为0,取反之后全为1,加1之后自然又全为0,最终取与只剩下最低位1。例如:6 (0b0110),-6(0b1010),取与后即为2(0b0010),最低位1的位置为1。利用这个性质,构建一个哈希表,保存所有的2的幂次和其对应幂次的值(log2,也就是低位上有多少个0)便于查找。输入为0的时候,返回64,表示全部都是0(64个)。

uint8_t CountTailingZeros(uint64_t num) {
    static const auto && pos_map = []() {
        std
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
bitsetC++ 标准库中的一个类,用于处理二进制位。下面是 bitset 的主要用法: 1. 创建 bitset 对象 可以通过以下方式创建 bitset 对象: ```cpp #include <bitset> // 创建一个大小为 10 的 bitset 对象,所有二进制位初始化为 0 std::bitset<10> bits1; // 从整数值创建 bitset 对象 std::bitset<10> bits2(0b1010); // 从字符串创建 bitset 对象 std::bitset<10> bits3("1010"); ``` 2. 访问二进制位 可以使用 `[]` 运算符或 `test()` 方法访问 bitset 对象中的二进制位,使用 `set()` 或 `reset()` 方法可以设置或复位二进制位。 ```cpp std::bitset<10> bits("1010"); // 访问第 0 位二进制位 bool b1 = bits[0]; bool b2 = bits.test(0); // 设置第 1 位二进制位 bits.set(1); // 复位第 2 位二进制位 bits.reset(2); ``` 3. bitset 的位运算 bitset 支持多种位运算操作,如按位与、按位或、按位异或、按位取反等。 ```cpp std::bitset<10> bits1("1010"); std::bitset<10> bits2("0110"); // 按位与 std::bitset<10> result1 = bits1 & bits2; // 按位或 std::bitset<10> result2 = bits1 | bits2; // 按位异或 std::bitset<10> result3 = bits1 ^ bits2; // 按位取反 std::bitset<10> result4 = ~bits1; ``` 4. bitset 的转换 bitset 可以转换为其他数据类型,如整数、字符串等。 ```cpp std::bitset<10> bits("1010"); // 转换为整数 int num = bits.to_ulong(); // 转换为字符串 std::string str = bits.to_string(); ``` 以上就是 bitset 的主要用法。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值