C++: 模拟实现类bitset
来源:互联网 发布:软件beta版已过期 编辑:程序博客网 时间:2024/05/19 18:40
C++: 模拟实现类bitset
标签: C++ bitset 位运算
by 小威威
1.bitset简介
bitset能实现对数字的位的操作,同时也能通过类似于数组的下标来访问各个位的数值,以执行相应的操作。模拟bitset就是用一个普通的数组来存储数据以达到模拟的目的。
先声明一下,本篇文章并不是讲述标准库中bitset这个类的用法,而是去讲述如何实现一个模拟bitset的类。
众所周知,int类型在64位系统中占4个字节,也就是32位,倘若我建立一个大小为5的数组,那么我就能存储5*32=160个位。然后我可以通过对数组的每个元素单独处理,通过位运算,来实现对位的操作。
2.类的实现
bitset.h如下:
#ifndef BITSET_H#define BITSET_H#include<iostream>#define N 5const int max_length = 32 * N;class bitset { private: int a[N]; public: bitset(); // 初始化全部置0 void set(int pos); // 将pos位变为1 void reset(int pos); // 将pos位变为0 int count() const; // 计算1的个数 bool test(int pos) const; // 检测位的数据是否为1 bool any() const; // 检测是否存在1 bool none() const; // 检测是否不存在1 bool all() const; // 检测是否全为1 bitset& operator&= (const bitset& b); bitset& operator|= (const bitset& b); bitset& operator^= (const bitset& b); bitset& operator= (const bitset& b); bitset& operator <<= (int pos); bitset& operator >>= (int pos); bitset operator~() const; bitset operator&(const bitset& b) const; bitset operator|(const bitset& b) const; bitset operator^(const bitset& b) const; bitset operator<<(int pos) const; bitset operator>>(int pos) const; bool operator== (const bitset& b) const; bool operator!= (const bitset& b) const; bool operator[] (int pos) const; // 下标访问 friend std::ostream& operator << (std::ostream& os, const bitset& s) { for (int i = N-1; i >= 0; i--) { for (int j = 31; j >= 0; j--) { if (s.a[i] & (1 << j)) os << 1; else os << 0; } } return os; }};#endif
要完成该模拟,需要有一定的位运算知识:
&, |, ^, ~, <<, >>,&=, |=, ^=, <<=, >>=所代表的含义以及执行的原理。(不懂的自行查书\百度\google)
本题需要的位运算的操作:(在最后的代码会呈现这些方法,所以有些方法没有附上代码只讲解了思路)
(1)将第一位变成1:
这个很简单,用位运算符就可以实现。
int i;i = i | 1;
(2)将第一位变成0:
int i;i = i & ~1;
(3)将某位变成0:
由(2)我们可以知道,要将某位变成0,需要&运算。如果我们能够创造出一个数字,其对应位的数字为0,其它位的数字为1,然后对二者进行&运算,就能将那一位变成0了。
(4)将某位变成1:
由(1)我们可以知道,要将某位变成1,需要|运算。如果我们能够创造出一个数字,使其对应为位1,其它位为0,然后对二者进行 | 运算,就能将那一位变成0了。
(5)统计二进制数中1的个数;
这个有两种方法:I.公式法;II. 逐位扫描法。
我们先来谈谈公式法。
int i, count = 0;while (i) { i &= i-1; count++;}
换句话来说就是”1的个数=(i&(i-1))的执行次数”。
第二种法方法就是逐位扫描法。
int num, count = 0;for (int i = 0; i < 32; i++) { if (num & (1<<i)) count++;}
(6)检验某位是0还是1。
在(5)中的if的条件就是用来判断位是0还是1.因为num & (1<<i)
在对应位为1时返回非0值,在对应位为0时返回0.
但是,我个人觉得最有意思的部分就是实现左移和右移。
有两种方法:
(1)一劳永逸法(质变法):
就是直接将所有位进行左移右移n位。采取的思路是对数组逐个元素进行移位操作,然后将移位后出现的补位进行重新赋值(也就是下一个元素的头几位).
(2)量变法:
就是将所有位进行逐次左移右移1位。
下面是这两种左移右移代码的对比:
// 一劳永逸法bitset& bitset :: operator <<= (int pos) { for (int i = N-1; i >= 1; i--) { a[i] <<= pos; for (int j = 0; j < pos; j++) { if (test(i*32+j-pos)) { (*this).set(i*32+j); } else { (*this).reset(i*32+j); } } } a[0] <<= pos; for (int i = 0; i < pos; i++) { (*this).reset(i); }}bitset& bitset :: operator >>= (int pos) { for (int i = 0; i < N-1; i++) { a[i] >>= pos; for (int j = 0; j < pos; j++) { if (test((i+1)*32+j)) { (*this).set((i+1)*32+j-pos); } else { (*this).reset((i+1)*32+j-pos); } } } a[N-1] >>= pos; for (int i = 0; i < pos; i++) { (*this).set(32*N-1-i); }}// 量变法bitset& bitset::operator <<= (int pos) { while (pos--) { for (int i = N-1; i >= 0; i--) { if (i == 0) { a[i] <<= 1; continue; } a[i] <<= 1; if (a[i-1] & (1 << 31)) a[i] |= 1; else a[i] &= ~1; } } return *this;}bitset& bitset::operator>>= (int pos) { while (pos--) { for (int i = 0; i < N; i++) { if (i == N-1) { a[i] >>= 1; continue; } a[i] >>= 1; if (a[i+1] & 1) a[i] |= 1 << 31; else a[i] &= ~(1 << 31); } } return *this;}
下面呈现实现该类的完整代码:
/*int a[N];*/# include "Bitset.h"#define N 5bitset :: bitset() { for (int i = 0; i < N; i++) { a[i] = 0; }}void bitset :: set(int pos) { int i = pos / 32; int j = pos % 32; a[i] = a[i] | (1 << j);}void bitset :: reset(int pos) { int i = pos / 32; int j = pos % 32; int value = 0; a[i] &= (~value^(1 << j));}int bitset :: count() const { int num[N]; for (int i = 0; i < N; i++) { num[i] = a[i]; } int count = 0; for (int i = 0; i < N; i++) { while (num[i]) { count++; num[i] &= num[i]-1; } } return count;}bool bitset :: test(int pos) const { int i = pos / 32; int j = pos % 32; if (a[i] & (1 << j)) { return true; } return false;}bool bitset :: any() const { for (int i = 0; i < N; i++) { for (int j = 0; j < 32; j++) { if (a[i] & (1 << j)) { return true; } } } return false;}bool bitset :: none() const { for (int i = 0; i < N; i++) { if (a[i] != 0) { return false; } } return true;}bool bitset :: all() const { for (int i = 0; i < N; i++) { if (~a[i] != 0) { return false; } } return true;}bitset& bitset :: operator&= (const bitset& b) { for (int i = 0; i < N; i++) { a[i] &= b.a[i]; } return *this;}bitset& bitset :: operator|= (const bitset& b) { for (int i = 0; i < N; i++) { a[i] |= b.a[i]; } return *this;}bitset& bitset :: operator^= (const bitset& b) { for (int i = 0; i < N; i++) { a[i] ^= b.a[i]; } return *this;}bitset& bitset :: operator= (const bitset& b) { for (int i = 0; i < N; i++) { a[i] = b.a[i]; } return *this;}bitset& bitset :: operator <<= (int pos) { for (int i = N-1; i >= 1; i--) { a[i] <<= pos; for (int j = 0; j < pos; j++) { if (test(i*32+j-pos)) { (*this).set(i*32+j); } else { (*this).reset(i*32+j); } } } a[0] <<= pos; for (int i = 0; i < pos; i++) { (*this).reset(i); }}bitset& bitset :: operator >>= (int pos) { for (int i = 0; i < N-1; i++) { a[i] >>= pos; for (int j = 0; j < pos; j++) { if (test((i+1)*32+j)) { (*this).set((i+1)*32+j-pos); } else { (*this).reset((i+1)*32+j-pos); } } } a[N-1] >>= pos; for (int i = 0; i < pos; i++) { (*this).set(32*N-1-i); }}bitset bitset :: operator~() const { bitset copy; for (int i = 0; i < N; i++) { copy.a[i] = ~a[i]; } return copy;}bitset bitset :: operator&(const bitset& b) const { bitset copy; for (int i = 0; i < N; i++) { copy.a[i] = a[i] & b.a[i]; } return copy;}bitset bitset :: operator|(const bitset& b) const { bitset copy; for (int i = 0; i < N; i++) { copy.a[i] = a[i] | b.a[i]; } return copy;}bitset bitset :: operator^(const bitset& b) const { bitset copy; for (int i = 0; i < N; i++) { copy.a[i] = a[i] ^ b.a[i]; } return copy;}bitset bitset :: operator<<(int pos) const { bitset copy; copy = *this; for (int i = N-1; i >= 1; i--) { copy.a[i] <<= pos; for (int j = 0; j < pos; j++) { if (copy.test(i*32+j-pos)) { copy.set(i*32+j); } else { copy.reset(i*32+j); } } } copy.a[0] <<= pos; for (int i = 0; i < pos; i++) { copy.reset(i); } return copy;}bitset bitset :: operator>>(int pos) const { bitset copy; copy = *this; for (int i = 0; i < N-1; i++) { copy.a[i] >>= pos; for (int j = 0; j < pos; j++) { if (copy.test((i+1)*32+j)) { copy.set((i+1)*32+j-pos); } else { copy.reset((i+1)*32+j-pos); } } } copy.a[N-1] >>= pos; for (int i = 0; i < pos; i++) { copy.set(32*N-1-i); } return copy;}bool bitset :: operator== (const bitset& b) const { for (int i = 0; i < N; i++) { if (a[i] != b.a[i]) { return false; } } return true;}bool bitset :: operator!= (const bitset& b) const { int count = 0; for (int i = 0; i < N; i++) { if (a[i] == b.a[i]) { count++; } } if (count == N) { return false; } return true;}bool bitset :: operator[] (int pos) const { int i = pos / 32; int j = pos % 32; if (a[i] & (1 << j)) { return true; } return false;}
以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!
- C++: 模拟实现类bitset
- [C++]bitset类用法
- bitset类的实现
- C++bitset类详解收集
- [C++]bitset用int数组实现
- 自己实现的Bitset类
- C++:模拟实现string类
- 模拟实现string类(c++)
- 【C++】模拟实现String类
- Python 实现类似C++的bitset类
- 【c/c++】bitset
- 模拟实现C++STL中的string类
- C++::模拟实现List
- c++:模拟实现vector
- 【c++】模拟实现堆
- 【C++】模拟实现栈
- 【C++】模拟实现队列
- bitset类
- LeetCode- Evaluate Reverse Polish Notation
- PAT (Advanced Level) Practise 1063 Set Similarity (25)
- iOS设置navigationBar背景透明
- WIN64上一种只需修改函数6个字节的INLINE HOOK方法
- JSON与null的解惑
- C++: 模拟实现类bitset
- Understanding LSTM Networks
- 搜索引擎原理 – 正排索引、倒排索引以及齐普夫法则
- ios学习资料
- php常用的的全局变量
- Bootstrap 提示框
- DRM security
- PerformanceCounter 性能计数器的使用
- 关于设计模式的思考——创建型模式