c++ STL bitset

基本操作:

bitset<n> b;	          b有n位,每位都为0
bitset<n> b(u);	          b是unsigned long型u的一个副本
bitset<n> b(s);	          b是string对象s中含有的位串的副本
bitset<n> b(s, pos, n);	  b是s中从位置pos开始的n个位的副本
bitset<10> s(string("11010"));  b是有01串转化而来
bitset<32> bitvec; 32位,全为0。

b.any()        b中是否存在置为1的二进制位?
b.none()       b中不存在置为1的二进制位吗?
b.count()      b中置为1的二进制位的个数
b.size()       b中二进制位的个数
b[pos]         访问b中在pos处的二进制位
b.test(pos)    b中在pos处的二进制位是否为1?
b.set()        把b中所有二进制位都置为1
b.set(pos)     把b中在pos处的二进制位置为1
b.reset()      把b中所有二进制位都置为0
b.reset(pos)   把b中在pos处的二进制位置为0
b.flip()       把b中所有二进制位逐位取反
b.flip(pos)    把b中在pos处的二进制位取反
b.to_ulong()   用b中同样的二进制位返回一个unsigned long值
cout<<b        把b中的位集输出到os流

b<<1;//b整体左移
b|=10; //b或 1010

下面是某些操作的详细讲解,转自:https://www.cnblogs.com/yifusuyi/p/10072729.html

修改与运算

bitset中每一个元素可以通过下标的方式访问。一个长度为NN的bitset下标编号为[0,N)[0,N)。

进行单点修改时,直接访问位置然后赋值即可:

s[pos] = x;

单点修改的复杂度为O(1)O(1)。

左移右移的写法与整形类似,移动后返回一个bitset,例如左移xx位:

bitset<N> k = s << x;

同时资瓷<<=和>>=操作:

s <<= x;

如果将字长放在RAM模型中,约定计算机字长为ww的话,一次左右移的复杂度为O(N/w)。其中在32位系统上,w = 32w = 32,64位系统上w = 64w = 64。由于bitset的绝大部分操作的复杂度都为O(N/w),以下内容中,若不特殊说明,则默认操作的复杂度同上。

如果仅仅考察运算量同输入规模的增长关系或不将字长纳入RAM模型,则可认为一次操作的复杂度为O(N),常数为132132或164164,这两种说法在文献上都有出现,在OI中为了方便计算运算量,一般使用第一种表达方法。以下内容一律使用O(N/w)的表示法。

同时bitset资瓷二元按位运算,即资瓷与、或、异或三个运算符:返回值为一个bitset。结果为运算符两侧的bitset按位运算的结果。

bitset<N> k = s & s0;

输入输出与转换

注意,输出时bitset是反着输出的,即第0位是从右向左数第1个:

cin >> s;                          // 1101
cout << s << std::endl;            // 000001101

从上述例子中可以看出,输入字符串的第【长度】位是集合的第1位。注意事项和使用std::string进行初始化的一致。

bitset提供两个转换函数,可以转换为std::string型,unsigned long int型(即unsigned int)。函数名为别为to_string()和to_ulong();

C++11标准下可以转换为unsigned long long int型,函数名为to_llong()

其中转换成std::string型会转换成01串,其他两个类型会按照二进制位转换成十进制数字。

当bitset大小大于32位时,转换成unsigned long int会导致RE,大于64位时,转换成unsigned long long int会产生RE:

// The default is that N is 8.
s.reset();
s[2] = true;
unsigned int s1 = s.to_ulong();
std::cout << s1 << std::endl;                   //4
unsigned long long int s2 = s.to_ullong();      //C++11
std::cout << s2 << std::endl;                   //4
std::string ss = s.to_string();                 
std::cout << ss << std::endl;                   //00000100

成员函数

reset

bitset的清空操作为reset。将集合内元素全部置零:

s.reset();

set

set有两种用法,第一种是直接调用set不带参数,会将bitset内所有元素置1,另一种是set后加两个参数,分别是pos和val,意为将bitset中第pos个元素的值置为v。当v为true时可以省略不写。

s.reset();
s.set()             //11111111
s.set(3,false)      //11110111
s.set(3)            //11111111

test

test有一个参数pos,返回一个bitset内第pos位的值。

s.reset();
s.set(7);
int k = s.test(7);      // k is true
k = s.test(6);          // k is false

any

bitset有一个成员函数为any,返回一个布尔量。若bitset内部存在一位的值为1,则返回true,否则返回false:

s.clear();
bool k = s.any();           //k is false
s[1] = true;
k = s.any()                 //k is true

复杂度同上。按照不同编译器版本的实现方法,.any()的常数甚至有可能小于理论值。

none

与any相对,返回一个布尔量,不存在任何一个位置的值为1则返回true,否则返回false。

s.clear();
bool k = s.none();          //k is true
s[1] = true;
k = s.none()                //k is false

count

count返回一个bitset内1的个数,是一个无符号整形:

s.reset();
int k = s.count();              // k is 0                   
s[1] = true;
k = s.count();                  // k is 1

需要注意的是目前扶苏已知的资料中,count的复杂度也是O(Nw)O(Nw)。

当然想知道0的个数可以用总长度减去count喽

flip

flip函数类似于按位取反,它的两个声明如下:

bitset& flip();
bitset& flip (size_t pos);

当调用s.flip()且括号内无参数时,会将集合内所有元素取反(0变1,1变0)

当调用s.flip(x)时,会将第x位取反(从0编号)

s.reset();
s[1] = true;    //s is "01000000"
s.flip();       //s is "10111111"
s.flip(1);      //s is "11111111"

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89151612