实现小尝试—C++ STL bitset
来源:互联网 发布:java ssh linux 编辑:程序博客网 时间:2024/05/30 05:40
关于bitset
bitset是C++ STL中的一种容器,用以标记一种0、1的位状态,可以声明一定长度的二进制位,然后每一位只能是0或者1。需要包含头文件<bitset>
。
如何小实现一下?
一、数据部分
可以使用一个unsigned long long的数组来保存,每一个数长度为64位,根据声明的长度来确定数组的长度。
于是数据结构的存储如下:
class BitState{protected: unsigned int bitlen; unsigned int numlen; unsigned long long *bits;};
我称其为BitState,有一个bitlen来保存声明的二进制位数,numlen保存数组的长度,bits指针指向存储数组。
二、操作部分
首先,我们需要构造函数:
可能需要包含以下几种:
BitState();//无参构造函数BitState(unsigned int len);//带参数len的构造函数,声明一个二进制长度为len的BitStateBitState(unsigned int len, unsigned long long val);//传入len的同时,传入一个无符号64位整形数,用这个数初始化BitState。BitState(const BitState &tmp);//拷贝构造函数,实现深拷贝
对于BitState();
实现:
BitState::BitState(){ bitlen = 8*sizeof(unsigned long long); numlen = 1; bits = new unsigned long long[numlen];}
默认就让它占一个unsigned long long大小,用sizeof防止不同编译器unsigned long long大小不一样,不过貌似都是64位的。
对于BitState(int len);
实现:
BitState::BitState(unsigned int len){ bitlen = len; numlen = (len+8*sizeof(unsigned long long)-1)/sizeof(unsigned long long)/8; bits = new unsigned long long[numlen];}
由于此处计算numlen应该使用上取整,对于x/y,上取整应该是(x+y-1)/y。
对于BitState(unsigned int len, unsigned long long val);
实现:
BitState::BitState(unsigned int len, unsigned long long val){ bitlen = len; numlen = (len+8*sizeof(unsigned long long)-1)/sizeof(unsigned long long)/8; bits = new unsigned long long[numlen]; if (len) bits[0] = val;}
这里需对len为0的情况进行判断,防止bits[0]越界。
对于BitState(const BitState &tmp);
实现:
BitState::BitState(const BitState &tmp){ bitlen = tmp.bitlen; numlen = tmp.numlen; bits = new unsigned long long[numlen]; for (int i = 0; i < numlen; ++i) bits[i] = tmp.bits[i];}
这里需要遍历bits来进行深拷贝。
然后,我们需要析构函数:
~BitState();
如下实现:
BitState::~BitState(){ delete bits;}
需要删除bits防止内存泄漏。
其次,我们还有实现一些bitset拥有的功能
bool any();//是否存在置为1的二进制位?bool none();//不存在置为1的二进制位吗?unsigned int count();//置为1的二进制位的个数unsigned int size();//二进制位的个数b[pos]//访问b中在pos处的二进制位bool test(unsigned int pos);//在pos处的二进制位是否为1?void set();//把所有二进制位都置为1void set(unsigned int pos);//在pos处的二进制位置为1void reset();//把所有二进制位都置为0void reset(unsigned int pos);//在pos处的二进制位置为0void flip();//把所有二进制位逐位取反void flip(unsigned int pos);//在pos处的二进制位取反unsigned long long to_ulong()//返回一个unsigned long值
接下来逐个实现,除了下标运算符用get函数实现,其余不变:
bool BitState::any(){ for (int i = 0; i < numlen; ++i) if (bits[i]) return true; return false;}
这个比较简单,判断是否有数为非负即可。
bool BitState::none(){ for (int i = 0; i < numlen; ++i) if (bits[i]) return false; return true;}
这个和any正好相反
unsigned int BitState::count(){ unsigned all = 0, tmp; for (int i = 0; i < numlen; ++i) { tmp = bits[i]; while (tmp) { all++; tmp = tmp&(tmp-1); } } return all;}
这里使用x&(x-1)这个来每次消掉x最低位1,来计算其中1的个数。
unsigned int BitState::size(){ return bitlen;}
这个直接返回即可。
bool BitState::get(unsigned int pos){ if (pos >= bitlen) return 0; int numsize = 8*sizeof(unsigned long long); int x = pos/numsize, y = pos%numsize; return bits[x]&(1ULL<<y);}
这个先计算出x在那个数中,然后计算出y在哪一位中,最后通过位运算取到结果。
bool BitState::test(unsigned int pos){ if (pos >= bitlen) return false; int numsize = 8*sizeof(unsigned long long); int x = pos/numsize, y = pos%numsize; return bits[x]&(1ULL<<y);}
和get一样。
void BitState::set(){ if (bitlen == 0) return; for (int i = numlen-2; i >= 0; --i) { bits[i] = 0; bits[i] = ~bits[i]; } unsigned int rest = bitlen-(numlen-1)*sizeof(unsigned long long); bits[numlen-1] = ((1ULL<<(rest-1))-1)<<1|1;}
首先对bitlen为0的情况特判,然后将低的numlen-1个数赋值为全1的二进制,最后的最高的rest位进行特殊处理。因为高出rest的位理论上应该是0。操作是先将1向左位移rest-1位(不位移rest位是防止溢出),然后减一,得到rest-1位全为1,然后左移一位,末尾补1。当然可以一位一位直接或1得到结果。
void BitState::set(unsigned int pos){ if (pos >= bitlen) return; int numsize = 8*sizeof(unsigned long long); int x = pos/numsize, y = pos%numsize; bits[x] |= 1ULL<<y;}
这个就是对这一位或一个1。
void BitState::reset(){ for (int i = 0; i < numlen; ++i) bits[i] = 0;}
全部置为0。
void BitState::reset(unsigned int pos){ if (pos >= bitlen) return; int numsize = 8*sizeof(unsigned long long); int x = pos/numsize, y = pos%numsize; bits[x] |= 1ULL<<y; bits[x] ^- 1ULL<<y;}
这个就是先对该位或1,让他变成1,然后用抑或取反。
void BitState::flip(){ if (bitlen == 0) return; for (int i = 0; i < numlen; ++i) bits[i] = ~bits[i]; unsigned int rest = bitlen-(numlen-1)*sizeof(unsigned long long); bits[numlen-1] &= ((1ULL<<(rest-1))-1)<<1|1;}
这个先全部取反,对于高rest位,与上一个rest位全1的,消掉剩余高位。
void flip(unsigned pos){ if (pos >= bitlen) return; if (test(pos)) reset(pos); else set(pos);}
通过判断该位是0还是1,来进行设置。
unsigned long long to_ulong(){ if (bitlen == 0) return 0; else return bits[0];}
返回第0个数,高出的全部算作溢出吧。
最后,我们还需要重载一些运算符:
BitState operator&(const BitState &tmp) const;BitState operator|(const BitState &tmp) const;BitState operator^(const BitState &tmp) const;BitState operator~() const;
BitState operator&(const BitState &tmp) const{ BitState ans(tmp.bitlen>bitlen ? tmp.bitlen : bitlen); ans.reset(); int minlen = tmp.numlen<numlen ? tmp.numlen : numlen; for (int i = 0; i < minlen; ++i) ans.bits[i] = tmp.bits[i]&bits[i]; return ans;}
直接抑或,直到到达某一个的最大长度。
BitState operator|(const BitState &tmp) const{ BitState ans(tmp.bitlen>bitlen ? tmp.bitlen : bitlen); ans.reset(); int minlen = tmp.numlen<numlen ? tmp.numlen : numlen; for (int i = 0; i < minlen; ++i) ans.bits[i] = tmp.bits[i]|bits[i]; for (int i = minlen; i < tmp.numlen; ++i) ans.bits[i] = tmp.bits[i]; for (int i = minlen; i < numlen; ++i) ans.bits[i] = bits[i]; return ans;}
这个和与不同的是,高出的部分全部赋值。由于只可能一长一短,所以最后两个for循环只会执行一个。
BitState operator|(const BitState &tmp) const{ BitState ans(tmp.bitlen>bitlen ? tmp.bitlen : bitlen); ans.reset(); int minlen = tmp.numlen<numlen ? tmp.numlen : numlen; for (int i = 0; i < minlen; ++i) ans.bits[i] = tmp.bits[i]^bits[i]; for (int i = minlen; i < tmp.numlen; ++i) ans.bits[i] = tmp.bits[i]; for (int i = minlen; i < numlen; ++i) ans.bits[i] = bits[i]; return ans;}
这个和或类似。
未完待续。
- 实现小尝试—C++ STL bitset
- C++/STL Bitset
- C++/STL bitset
- C++/STL bitset
- C++/STL Bitset (转)
- C++/STL Bitset (转)
- C++/STL Bitset (转)
- [C++] STL (Algorithm,bitset)
- C++/STL Bitset (转)
- C++/STL Bitset (转)
- STL——bitset
- C++/STL Bitset (转+修改)
- c++STL通用容器 之 bitset容器
- C++STL之bitset位集合容器
- C++STL bitset介绍与使用方法
- c++stl的bitset位集合容器
- STL-bitset
- C++: 模拟实现类bitset
- Android 使用DisplayImageOptions加载头像 自定义圆形头像
- Flask-Blueprint
- 合并多个python list以及合并多个 django QuerySet 的方法在用python或者django写一些小工具应用的时候,有可能会遇到合并多个list到一个 list 的情况。单纯从技
- 音频信号分帧
- 匹配所有合法的HTML标签的正则表达式
- 实现小尝试—C++ STL bitset
- CoordinatorLayout与CollapsingToolbarLayout实现视差滚动动画和Toolbar滚动
- 字符串的替换
- 【通讯术语】MSIN
- 网页加载去除网页元素 webView
- Java Double 保留两位小数点
- Spark初学笔记
- Android中如何引入text文件
- Java重修之路(七)面向对象之静态,主函数,Doc文档,静态代码块,对象初始化过程,单例设计模式