Boost (2): dynamic_bitset二进制数

/*
*  boost库中数据容器之一:dynamic_bitset
*   配置环境: win32 + codeblock + mingw32-g++ + boost.1.66
*   author  : Ranger_roger
*   time    : 2018//3/2
*
*  采用位运算往往可以取得意想不到的性能提升,位运算必然和二进制位数关联,C++为二进制位数提
*  供了两个工具std::vector和std::bitset
*  前者并不是容器,虽可动态增长,但是位运算受限;后者的bitset是标准容器,支持多样的位运算
*  但是大小固定,无法动态增长size。
*  boost::dynamic_bitset则是综合两者的优点
*/

/*
template 
//Block指示以何种整数类型存储二进制位,必须是一个无符号整数,默认是unsigned long,如果二进制
//数不超过32位,为节省空间,可以采用更小的Block类型,如果unsigned char unsigned short
//Allocator是类内部使用的内存分配器,默认为std::allocator,一般这两个模板形参无需变动
class dynamic_bitset
{
    // Portability note: member function templates are defined inside
    // this class definition to avoid problems with VC++. Similarly,
    // with the member functions of nested classes.
    //
    // [October 2008: the note above is mostly historical; new versions
    // of VC++ are likely able to digest a more drinking form of the
    // code; but changing it now is probably not worth the risks...]

    BOOST_STATIC_ASSERT((bool)detail::dynamic_bitset_impl::allowed_block_type::value);
    typedef std::vector buffer_type;

public:
    typedef Block block_type;
    typedef Allocator allocator_type;
    typedef std::size_t size_type;
    typedef typename buffer_type::size_type block_width_type;

    BOOST_STATIC_CONSTANT(block_width_type, bits_per_block = (std::numeric_limits::digits));
    BOOST_STATIC_CONSTANT(size_type, npos = static_cast(-1));

    explicit dynamic_bitset();   //显式的无参构造函数,拒绝隐式调用
    dynamic_bitset(const dynamic_bitset& b);

    void swap(dynamic_bitset& b);   //基本操作集合
    void resize(size_type num_bits, bool value = false);
    void clear();
    void push_back(bool bit);
    void append( Block block);
    //注意因为dynamic_bitset也并非严格意义上的容器,故而也没有begin()和end()迭代器遍历接口

    bool  operator[](size_type pos) const; //操作符[]重载
    dynamic_bitset& operator&=(const dynamic_bitset& b);
    dynamic_bitset& operator|=(const dynamic_bitset& b);
    ...

    dynamic_bitset&  set();     //bit翻转
    dynamic_bitset&  reset();
    dynamic_bitset&  flip();    //位图取反

    bool test(size_type n) const;  //bit测试
    bool any() const;     //检测位图,若有任意1,则返回true
    bool none() const;    //检测位图,若有任意1,则返回false
    dynamic_bitset operator~() const; //重载取反符号
    size_type  count() const;  //检测位图中有1的数目

    unsigned long to_ulong() const; //转型到ulong
    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;
*/

#include 
#include 
#include 
#include  //定义了BOOST_BINARY宏

using namespace std;
using namespace boost;

int main()
{
    dynamic_bitset<> db1;
    dynamic_bitset<> db2(10);
    dynamic_bitset<> db3(0x16,
                            BOOST_BINARY(10101));
    //大小为22,并采用boost的编译器宏BOOST_BINARY在编译器直接创建一个二进制数,没有运行时开销
    dynamic_bitset<> db4(string("0100"));//使用string构建临时对象,存在运行期开销
    dynamic_bitset<> db5(db3);

    dynamic_bitset<> db6;
    db6 = db4;

    cout << hex << db5.to_ulong() << endl; //转换为整数, 0x15 = 21
    cout << db4[0] << db4[1] << db4[2] << endl; //dynamic_bitset从高到低存储二进制位,即[0]对应最低位
    cout << db2 << endl;
    cout << db6 << endl;

    //“容器”操作
     cout << "*****************size-related operation resize/size/clear" << endl;
    db2.resize(20, true); //扩展
    cout << db2 << endl;
    db2.resize(15);  //收缩
    cout << db2 << endl;
    db2.clear();     //清空
    cout << "db2:" << db2 << endl;

    assert(db2.size() == 0 && db2.empty() ); //判断db2是否为空

    //判断一个dynamic_bitset占据了几个block,如果block是默认的unsigned long,则对应为8*8即64个字节
    //assert(dynamic_bitset<>(64).num_blocks() == 2);
    assert(dynamic_bitset<>(65).num_blocks() == 3);
    cout << dynamic_bitset<>(64).num_blocks() << endl; //2
    cout << sizeof(unsigned long) << endl; //4

    cout << db6 << endl;  //0100
    cout << db6.size() << endl; //4
    db6.append(BOOST_BINARY(101));
    cout << db6 << endl; //000000000000000000000000000000001010100
    cout << db6.size() << endl; //24

    //位运算操作,使用了代理技术,存在class class的内部类,用以完成细粒度元素的位运算
     cout << "*****************bit-op operation ^/&/|" << endl;
    dynamic_bitset<> db7(4, BOOST_BINARY(1010));
    db7[0] &= 1;  //与
    db7[1] ^= 1;  //异或
    cout << db7 << endl; //1000

    dynamic_bitset<> db8(4, BOOST_BINARY(0101));
    assert(db7 > db8 );

    cout << (db7 ^ db8) << endl; //1101
    cout << (db7 | db8) << endl; //1101
    cout << (db7 & db8) << endl; //0000

    //返回元素
     cout << "*****************statistical operation test/any/none/count" << endl;
    cout << db8.test(0) << endl; //查看二进制数的第n位是否为1 //1
    cout << db8.any() << endl; //查看二进制数是否有任意1  //1
    cout << db8.none() << endl; //any的反操作  //0
    cout << db8.count() << endl; //统计db8中所有值为1的元素的数量 //2
    cout << db8.find_first() << endl; //从第0位置开始查找,返回第一个值为1的位置
    cout << db8.find_next(0) << endl; //从第n位置开始查找,返回第一个值为1的位置,若找不到则返回npos

    cout << "*****************reverse operation set/reset/flip" << endl;
    cout << db8 << endl; //0101
    db8.set(); //可以置全部或特定位置为1或0,默认是1
    cout << db8 << endl; //1111
    db8.reset(); //可以置全部或特定为0
    cout << db8 << endl; //0000
    db8.flip();//将特定位置或全部位置翻转
    cout << db8 << endl; //1111

    cout << "*****************type conversion to_ulong/to_string" << endl;
    cout << std::dec << db8.to_ulong() << endl;
    string str;
    to_string(db8, str);
    cout << str << endl;

    cout << "*****************list operation is_subset_of/is_proper_subset_of" << endl;
    dynamic_bitset<> db9(4, BOOST_BINARY(11)); //即便是做子集判断,依旧要求两个dynamic_bitset的size是等价的
    dynamic_bitset<> db10(db8);
    assert(db9.is_proper_subset_of(db8)); //真子集
    assert(db10.is_subset_of(db8)); //子集

    cout << "*****************a demo for selecting prime number" << endl;
    int n;
    cin >> n;
    dynamic_bitset<> db(n); //初始化为size=n,全部位置为1

    db.set(); //翻转,全部置为1

    for (dynamic_bitset<>::size_type i = db.find_next(1);
         i != dynamic_bitset<>::npos;
         i = db.find_next(i) ) //因为dynamic_bitset不是标准容器,所以不能使用迭代器,也不能用for+auto范围迭代
    {
        for (dynamic_bitset<>::size_type j = db.find_next(i);
             j != dynamic_bitset<>::npos;
             j = db.find_next(j))
             {
                 if (j % i == 0)
                 {
                     db[j] = 0;
                 }
             }
    }

    for (dynamic_bitset<>::size_type i = db.find_next(2);
        i != dynamic_bitset<>::npos;
        i = db.find_next(i))
        {
            cout << i << ", ";
        }  //如输入10,则打印: 3, 5, 7,
    return 0;
}

你可能感兴趣的:(boost)