• 【STL】bitset的模拟实现


    ⭐博客主页:️CS semi主页
    ⭐欢迎关注:点赞收藏+留言
    ⭐系列专栏:C++进阶
    ⭐代码仓库:C++进阶
    家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!


    一、函数接口总览

    #include
    #include
    using namespace std;
    
    namespace JRH
    {
    	// 模拟实现位图
    	template<size_t N>
    	class bitset
    	{
    	public:
    		// 构造函数
    		bitset();
    
    		// set设置位
    		void set(size_t pos);
    
    		// reset清空
    		void reset(size_t pos);
    
    		//反转位
    		void flip(size_t pos);
    
    		//获取位的状态
    		bool test(size_t pos);
    
    		//获取可以容纳的位的个数
    		size_t size();
    
    		//获取被设置位的个数
    		size_t count();
    
    		//判断位图中是否有位被设置
    		bool any();
    
    		//判断位图中是否全部位都没有被设置
    		bool none();
    
    		//判断位图中是否全部位都被设置
    		bool all();
    
    		//打印函数
    		void Print();
    
    	private:
    		vector<int> _bits;
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    二、bitset类的实现

    1、构造函数

    在构造位图时,我们需要根据所给位数N,创建一个N位的位图,并且将该位图中的所有位都初始化为0。

    我们知道,一个整型有32个比特位,但我们传来的位图肯定不可能是32的倍数的,所以我们就需要在结束完/32以后就加1,往后多开一个32个位的空间,将多余的空间放到下一个位图中。

    如下图:我们假如有40位,我们则需要开两个整型(多开一个),并将这40放进去。
    在这里插入图片描述

    		// 构造函数
    		bitset()
    		{
    			_bits.resize(N / 32 + 1, 0);
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、set(设置)

    在这里插入图片描述

    		// set设置位
    		void set(size_t pos)
    		{
    			assert(pos < N);
    			// 除一下找到在第几个
    			int i = pos / 32;
    			int j = pos % 32;
    			_bits[i] |= (1 << j);
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、reset(重置)

    在这里插入图片描述

    		// reset清空
    		void reset(size_t pos)
    		{
    			assert(pos < N);
    
    			// 除一下找到在第几个
    			int i = pos / 32;
    			int j = pos % 32;
    			_bits[i] &= (~(1 << j));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、flip(反转)

    在这里插入图片描述

    		//反转位
    		void flip(size_t pos)
    		{
    			assert(pos < N);
    
    			// 找到在哪里
    			int i = pos / 32;
    			int j = pos % 32;
    			_bits[i] ^= (1 << j);
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5、test(获取位状态)

    在这里插入图片描述

    		//获取位的状态
    		bool test(size_t pos)
    		{
    			assert(pos < N);
    
    			// 找到位置
    			int i = pos / 32;
    			int j = pos % 32;
    			if (_bits[i] & (1 << j))
    				return true;
    			else
    				return false;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    6、size(算长度/个数)

    size成员函数用于获取位图中可以容纳的位的个数,即直接计算参数模板中的位的个数即可。

    		//获取可以容纳的位的个数
    		size_t size()
    		{
    			return N;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    7、count(算位图中被设置的个数)

    在这里插入图片描述

    		//获取被设置位的个数
    		size_t count()
    		{
    			size_t count = 0;
    			for (auto e : _bits)
    			{
    				int num = e;
    				// 计算1的个数
    				while (num)
    				{
    					num = num & (num - 1);
    					count++;
    				}
    			}
    			return count;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8、any(该位图中是否有位被设置)

    只需要一个for循环,如果有一个是1则返回true,遍历结束都没有1则返回false。

    		//判断位图中是否有位被设置
    		bool any()
    		{
    			for (auto e : _bits)
    			{
    				if (e != 0)
    				{
    					return true;
    				}
    			}
    			return false;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    9、none(判断位图中是否全部位都没有被设置)

    只需要返回any的逻辑取反即可。

    		//判断位图中是否全部位都没有被设置
    		bool none()
    		{
    			return !any();
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10、all(判断是否全被设置)

    1、先检查前n-1个整数的二进制是否为全1
    2、再检查最后一个整数的前N%32个比特位是否为全1

    在这里插入图片描述

    		//判断位图中是否全部位都被设置
    		bool all()
    		{
    			size_t n = _bits.size();
    			// 先判断前n-1个整数
    			for (size_t i = 0; i < n - 1; ++i)
    			{
    				// 取反后不全为0则取反前不全为1
    				if (~_bits[i] != 0)
    				{
    					return false;
    				}
    			}
    			// 再判断第n个整数的bite位
    			for (size_t j = 0; j < N % 32; j++)
    			{
    				if ((_bits[n - 1] & (1 << j)) == 0)
    				{
    					return false;
    				}
    			}
    			return true;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    11、Print(打印函数)

    打印函数就是先打印前n-1个数值的比特位的值,再打印最后一个整数的32个比特位中前面被设置的值。

    		//打印函数
    		void Print()
    		{
    			int count = 0;
    			size_t n = _bits.size();
    
    			// 先打印前n-1
    			for (int i = 0; i < n - 1; i++)
    			{
    				for (int j = 0; j < 32; j++)
    				{
    					if (_bits[i] & (1 << j))
    					{
    						cout << "1";
    					}
    					else
    					{
    						cout << "0";
    					}
    					count++;
    				}
    			}
    
    			// 再打印第n个的比特位
    			for (int j = 0; j < N % 32; j++)
    			{
    				if (_bits[n - 1] & (1 << j))
    				{
    					cout << "1";
    				}
    				else
    				{
    					cout << "0";
    				}
    				count++;
    			}
    			cout << endl;
    			cout << " " << count << endl;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    postgres数据库报错无法写入文件 “base/pgsql_tmp/pgsql_tmp215574.97“: 设备上没有空间
    NLP(2)--Transformer
    wireshark常见使用表达式
    Spark系列—spark简介
    基于JavaWeb实现的校园新闻发布系统
    基于centos7安装nginx
    【电子通识】USB3.0和USB2.0有什么区别?
    【UML】活动图Activity Diagram、状态机图State Machine Diagram、顺序图Sequence Diagram
    【译】VisualStudio.Extensibility 17.10:用 Diagnostics Explorer 调试您的扩展
    JavaScript中的事件捕获(event capturing)和事件冒泡(event bubbling)
  • 原文地址:https://blog.csdn.net/m0_70088010/article/details/133959614