dynamic_bitset
C++标准为处理二进制数值提供了两个工具:vector<bool>和bitset.vector<bool> 是对元素类型为bool的vector特化,它内部并不真正存储bool值而是以bit来压缩保存,使用代理技术来操作bit,造成的后果就是它很像容器,大多数情况下的行为与标准容器一样,但它不是容器,不满足容器的定义。bitset与vector<bool> 类似,同样存储二进制,但它的的大小固定
·
C++标准为处理二进制数值提供了两个工具:vector<bool>和bitset.
vector<bool> 是对元素类型为bool的vector特化,它内部并不真正存储bool值而是以bit来压缩保存,使用代理技术来操作bit,造成的后果就是它很像容器,大多数情况下的行为与标准容器一样,但它不是容器,不满足容器的定义。
bitset与vector<bool> 类似,同样存储二进制,但它的的大小固定,而且比vector<bool>支持更多的位运算。
两者的优缺点:vector<bool>可以动态增长,但不能方便地进行位运算;bitset则可以方便地对容纳的二进制位做位运算,但是不能动态的增长。
boost.dynamic_bitset 的出现恰好填补了这两者之间的空白,它类似标准库的bitset,提供丰富的位运算,同时长度又是动态可变的。
类摘要
template <typename Block, typename Allocator>
class dynamic_bitset
{
public:
explicit dynamic_bitset();/// 构造函数
dynamic_bitset(const dynamic_bitset& b);
/// 基本操作
void swap(dynamic_bitset& b);
void resize(size_type num_bit, bool value = false);
void clear();
void push_back(bool bit);
void apend(Block block);
/// 操作符重载
bool operator[](size_type pos)const;
dynamic_bitset& operator&=(const dynamic_bitset& b);
dynamic_bitset& operator|=(const dynamic_bitset& b);
...
///
dynamic_bitset& set();
dynamic_bitset& reset();
dynamic_bitset& filp();
/// 测试
bool test(size_type n) const;
bool any() const;
bool none() const;
dynamic_bitset operator~()const;
size_type count() const;
/// 转型到 ulong
unsigned long to_ulong() cosnt;
/// 容量操作
size_type size()const;
size_type num_blocks() const;
size_type max_size() const;
bool empty() const;
/// 集合操作
bool is_subset_of(const dynamic_bitset& a)const;
bool is_proper_subset_of(const dynamic_bitset& a)const;
/// 查找元素
size_type find_first()const;
size_type find_next(size_type pos) const;
};
dynamic_bitset 几乎与std::bitset相同,包括接口和行为,唯一的区别是:dynamic_bitset的大小是在构造函数中又参数决定的,而且运行时时动态可变的。
注意:与vecor<bool>和bitset一样,dynamic_bitset不符合标准容器的定义,不是严格意义样的容器,不提供迭代器的支持。
创建与赋值
dynamic_bitset的第一个模板参数Block指示dynamic_bitset以什么整数类型存储二进制位,必须是一个无符号整数,默认是unsigned long。第二个参数Allocator是类内部使用的内存分配器,默认是std::allocator<Block>。
- 不带参数的构造函数创建一个大小为0的dynamic_bitset对象
- 传入参数制定dynamic_bitset的大小并赋初值,像标准容易一样
- 从另一个dynamic_bitset拷贝构造
- 从 01 字符串构造(与std::bitset一样都要求是std::string字符串)
dynamic_bitset<> db1; /// 空的dynamic_bitset 对象
dynamic_bitset<> db2(10); /// 创建一个大小为10的对象
dynamic_bitset<> db3(0x16,
BOOST_BINARY(10101)); //注意这里,使用了boost宏 BOOST_BINARY 构造一个编译期的二进制数
dynamic_bitset<> db4(string("0100")); ///字符串构造
dynamic_bitset<> db5(db3);
dynamic_bitset<> db6;
db6 = db4;
cout << hex << db5.to_ulong() << endl;
cout << db4[0] << db4[1] << db4[2] << endl; /// operator[]
容器操作
dynamic_bitset 可以使用resize()成员函数在运行时调整容器的大小,扩展或者收缩都是允许的,并且可以用true/false或者1/0指定扩展后新元素的默认值。
如果是扩展,那么原来有的二进制位保持不变,新增的二进制位被指为指定的值:如果是收缩,那么收缩后容量的二进制位保持不变,多余的二进制位被抛弃,此时设置新元素的默认值是无意义的。
dynamic_bitset<> db;///空的dynamic_bitset对象
db.resize(10, true);///扩展为10个二进制,全部为1
cout << db << endl; /// 1111111111
db.resize(5); /// 缩小容量为5个二进制
cout << db << endl; /// 11111
{
dynamic_bitset<> db(5,BOOST_BINARY(01110));
cout << db << endl;
assert(db.size() == 5);
db.clear(); /// 清空 效率比resize效率高
assert(db.empty()&& db.size()==0);
}
/// dynamic_bitset 使用Block来存储二进制位,因此,size()函数不能
/// 反映dynamic_bitset所占用的内存大小。
assert(dynamic_bitset<>(64).num_blocks()==1);
assert(dynamic_bitset<>(65).num_blocks()==2);
{
dynamic_bitset<> db(5,BOOST_BINARY(01001));
db.push_back(true); /// 实际上是项二进制最高位添加
assert(db.to_ulong() == BOOST_BINARY_UL(101001));
}
{
dynamic_bitset<> db(5,BOOST_BINARY(01001));
db.append(BOOST_BINARY(101));/// 实际上是项二进制最高位添加
assert(db.size() == sizeof(unsigned long)*8 + 5);
cout << db << endl; //0000000000000000000000000000010101001
}
位运算与比较运算
与vector<bool>相似,dynamic_bitset也运用了代理技术,重载了operator[], operator|等操作符,因此可以像普通数字一样访问其中的二进制位,而且能对二进制或者整个容器做任意位运算,当然吹不能做加减乘除
dynamic_bitset<> db1(4, BOOST_BINARY(1010));
db1[0] &= 1; ///按位与运算
db1[1] ^= 1; ///按位异或运算
cout << db1 << endl;/// 1000
dynamic_bitset<> db2(4, BOOST_BINARY(0101));
assert(db1 > db2);
cout << (db1 ^ db2) << endl;///1101
cout << (db1 | db2) << endl;///1101
访问元素
除了使用operator[]直接访问容器内的元素外,dynamic—bitset还有个成员函数用于测试或者重置二进制位。
1.test()函数检测第n位是否为1
2.如果容器中存在二进制位1,那么any()返回true
3.如果容器中不存在二进制位1,那么none()返回true
4.count()函数统计容器中所有值为1的元素数量
5.set()函数可以置全部或者特定的位置的值为0或者1
6.reset()可以置全部或者特定的位置的值为0
7.flip()可以反转全部或者特定的位置的值
8.find_first()从0位置开始查找,返回第一个值为1的位置
9.find_next(pos)从第pos位置开始差值,返回第一个值为1的位置,如果查找不到,返回npos.
“`
dynamic_bitset<> db(4, BOOST_BINARY(0101));
assert(db.test(0) && !db.test(1));
assert(db.any() && !db.none());
assert(db.count() == 2); ///值为1 的个数
{
dynamic_bitset<> db(4, BOOST_BINARY(0101));
db.flip(); /// 反转
assert(db.to_ulong() == BOOST_BINARY(1010));
db.set();
assert(!db.none());
db.reset();
assert(!db.any() );
db.set(1, 1);
assert(db.count() == 1);
}
{
dynamic_bitset<> db(5, BOOST_BINARY(00101));
auto pos = db.find_first();
assert(pos == 0);
pos = db.find_next(pos);
assert(pos == 2);
}
更多推荐
已为社区贡献1条内容
所有评论(0)