STL detailed explanation (fifteen) - simulation implementation of bitset (bitmap)

Overview of the function interfaces of the bitset class

namespace cl
{
    
    
	//模拟实现位图
	template<size_t N>
	class bitset
	{
    
    
	public:
		//构造函数
		bitset();
		//设置位
		void set(size_t pos);
		//清空位
		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; //位图
	};
}

Note: In order to prevent naming conflicts with the bitset class in the standard library, the mock implementation needs to be placed in its own namespace.

Implementation of bitset class

Constructor

When constructing a bitmap, we need to create a bitmap of N bits according to the given number of bits N, and initialize all bits in the bitmap to 0.

An integer has 32 bits, so an N-bit bitmap needs to use N/32 integers, but the actual number of integers we need is N/32+1, because the given non-type template The value of parameter N may not be an integer multiple of 32.

For example, when N is 40, we need to use two integers, ie 40/32+1=2.
insert image description here
code show as below:

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

set、reset、flip、test

The set member function is used to set bits.

The method to set the specified bit in the bitmap is as follows:

  1. Calculate the bit at the jth bit of the ith integer.
  2. Shift 1 to the left by j bits and perform an OR operation with the ith integer.

insert image description here
code show as below:

//设置位
void set(size_t pos)
{
    
    
	assert(pos < N);

	//算出pos映射的位在第i个整数的第j个位
	int i = pos / 32;
	int j = pos % 32;
	_bits[i] |= (1 << j); //将该位设置为1(不影响其他位)
}

The reset member function is used to clear bits.

The method to clear the specified bit in the bitmap is as follows:

  1. Calculate the bit at the jth bit of the ith integer.
  2. Shift 1 to the left by j bits, then invert the whole, and perform AND operation with the i-th integer.

insert image description here
code show as below:

//清空位
void reset(size_t pos)
{
    
    
	assert(pos < N);

	//算出pos映射的位在第i个整数的第j个位
	int i = pos / 32;
	int j = pos % 32;
	_bits[i] &= (~(1 << j)); //将该位设置为0(不影响其他位)
}

The flip member function is used to reverse the bits.

The way to invert the bits specified in the bitmap is as follows:

  1. Calculate the bit at the jth bit of the ith integer.
  2. Shift 1 to the left by j bits and perform the XOR operation with the ith integer.

insert image description here
code show as below:

//反转位
void flip(size_t pos)
{
    
    
	assert(pos < N);

	//算出pos映射的位在第i个整数的第j个位
	int i = pos / 32;
	int j = pos % 32;
	_bits[i] ^= (1 << j); //将该进行反转(不影响其他位)
}

The test member function is used to get the state of the bit.

The method to get the state of the bit specified in the bitmap is as follows:

  1. Calculate the bit at the jth bit of the ith integer.
  2. Shift 1 left by j bits and AND with the ith integer to get the result.
  3. If the result is non-zero, the bit is set, otherwise the bit is not set.

insert image description here
code show as below:

//获取位的状态
bool test(size_t pos)
{
    
    
	assert(pos < N);

	//算出pos映射的位在第i个整数的第j个位
	int i = pos / 32;
	int j = pos % 32;
	if (_bits[i] & (1 << j)) //该比特位被设置
		return true;
	else //该比特位未被设置
		return false;
}

size、count

The size member function is used to obtain the number of bits that can be accommodated in the bitmap.

We can directly return the given non-type template parameter.

//获取可以容纳的位的个数
size_t size()
{
    
    
	return N;
}

The count member function is used to get the number of bits set in the bitmap.

To get the number of bits set in the bitmap, that is, to count the number of 1s in the bitmap, we only need to count the number of 1s in each integer binary in turn, and then add them to get 1 in the bitmap number of.

The way to count the number of 1's in binary is as follows:

  1. The new n is obtained by ANDing the original number n with n - 1 .
  2. Determine whether n is 0, if n is not 0, continue to the first step.

This continues until n is finally 0, at which point the operation has been performed a few times to show how many 1s are in the binary.

Because every time this operation is performed, the rightmost 1 in the binary is eliminated. The example picture is as follows: The
insert image description here
code is as follows:

//获取被设置位的个数
size_t count()
{
    
    
	size_t count = 0;
	//将每个整数中1的个数累加起来
	for (auto e : _bits)
	{
    
    
		int num = e;
		//计算整数num中1的个数
		while (num)
		{
    
    
			num = num&(num - 1);
			count++;
		}
	}
	return count; //位图中1的个数,即被设置位的个数
}

any、none、all

The any member function is used to determine whether a bit is set in the bitmap.

We just need to iterate over each integer, if all these integers are 0, it means that no bit in the bitmap has been set.
Although the bitmap may not contain all the bits of the last integer, since all the bits of the integer are initialized to 0 when we construct the bitmap, it will not affect the judgment here.
insert image description here
code show as below:

//判断位图中是否有位被设置
bool any()
{
    
    
	//遍历每个整数
	for (auto e : _bits)
	{
    
    
		if (e != 0) //该整数中有位被设置
			return true;
	}
	return false; //全部整数都是0,则没有位被设置过
}

The none member function is used to determine whether all the bits in the bitmap are not set.

Whether all the bits in the bitmap are not set is actually the reverse side of the bit that is set in the bitmap, so the none member function directly calls the any member function, and then inverts the return value and then returns.

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

The all member function is used to determine whether all bits in the bitmap are set.

The judgment process is divided into two steps:

  1. First check whether the binary of the first n-1 integers are all 1s.
  2. Then check whether the first N% 32 bits of the last integer are all 1s.

It should be noted that if the bitmap does not contain all the bits of the last integer, the binary of the last integer will not be all 1s anyway, so when judging the last integer, only the bits contained in the bitmap should be judged. .
insert image description here
code show as below:

//判断位图中是否全部位都被设置
bool all()
{
    
    
	size_t n = _bits.size();
	//先检查前n-1个整数
	for (size_t i = 0; i < n - 1; i++)
	{
    
    
		if (~_bits[i] != 0) //取反后不为全0,说明取反前不为全1
			return false;
	}
	//再检查最后一个整数的前N%32位
	for (size_t j = 0; j < N % 32; j++)
	{
    
    
		if ((_bits[n - 1] & (1 << j)) == 0) //该位未被设置
			return false;
	}
	return true;
}

print function

A printing function can be implemented to check the correctness of the above code. When printing a bitmap, it is enough to traverse the bits contained in the bitmap and print. During the process of printing the bitmap, you can count the number of bits in the bitmap by the way. , compare count with the non-type template parameter N we passed in, and we can judge whether the size of the bitmap is in line with our expectations.

//打印函数
void Print()
{
    
    
	int count = 0;
	size_t n = _bits.size();
	//先打印前n-1个整数
	for (size_t i = 0; i < n - 1; i++)
	{
    
    
		for (size_t j = 0; j < 32; j++)
		{
    
    
			if (_bits[i] & (1 << j)) //该位被设置
				cout << "1";
			else //该位未被设置
				cout << "0";
			count++;
		}
	}
	//再打印最后一个整数的前N%32位
	for (size_t j = 0; j < N % 32; j++)
	{
    
    
		if (_bits[n - 1] & (1 << j)) //该位被设置
			cout << "1";
		else //该位未被设置
			cout << "0";
		count++;
	}
	cout << " " << count << endl; //打印总共打印的位的个数
}

Guess you like

Origin blog.csdn.net/chenlong_cxy/article/details/122508813