BitSet/Linux/BitSet.hpp

131 lines
3.3 KiB
C++

#pragma once
#include <iostream>
#include <vector>
#include <stdexcept>
namespace Lenyiin
{
class BitSet
{
private:
// 计算某个位属于哪个块,并且在该块中的哪个位置
std::pair<size_t, size_t> getPosition(size_t index) const
{
if (index >= _bitsize)
{
throw std::out_of_range("Index out of range");
}
// 确定映射在哪个 unsigned long 中
size_t block = index / (sizeof(unsigned long) * 8);
// 确定映射在 unsigned long 中的哪一位
size_t offset = index % (sizeof(unsigned long) * 8);
return {block, offset};
}
public:
BitSet(size_t size)
{
_bits.resize(size / sizeof(unsigned long) * 8 + 1, 0);
_bitsize = size;
}
// 置 1
void set(size_t index)
{
auto [block, offset] = getPosition(index);
// 左移右移这里的左右不是方向, 左移是向高位移, 右移是向低位移
// C语言设计的bug, 历史遗留问题, 容易让人误导, 计算机技术发展百花齐放, 再融合统一
_bits[block] |= (1UL << offset); // 第 pos 个位置 1
}
// 置 0
void reset(size_t index)
{
auto [block, offset] = getPosition(index);
_bits[block] &= ~(1UL << offset); // 第 pos 个位置 0
}
// 反转
void flip(size_t index)
{
auto [block, offset] = getPosition(index);
_bits[block] ^= (1UL << offset); // 使用位异或运算反转位
}
// 判断 x 在不在 (也就是说 x 映射的位置是否为 1)
bool test(size_t index) const
{
auto [block, offset] = getPosition(index);
// bool 0 就是 false, 非 0 就是 true
return _bits[block] & (1UL << offset);
}
// 全部置 1
void set()
{
for (auto &block : _bits)
{
block = ~0UL;
}
}
// 全部置 0
void reset()
{
for (auto &block : _bits)
{
block = 0;
}
}
// 全部反转
void flip()
{
for (auto &block : _bits)
{
block = ~block;
}
}
// 获取位数
size_t size() const
{
return _bitsize;
}
// 统计所有位中为 1 的个数
size_t count() const
{
size_t cnt = 0;
for (auto block : _bits)
{
cnt += __builtin_popcountl(block); // 使用 GCC 内置函数统计1的个数
}
return cnt;
}
// 打印内容(调试用途)
void print()
{
for (size_t i = 0; i < _bitsize; i++)
{
std::cout << (test(i) ? '1' : '0');
if ((i + 1) % 8 == 0)
{
std::cout << " ";
}
}
std::cout << std::endl;
}
private:
// int* _bits;
std::vector<unsigned long> _bits;
size_t _bitsize; // 映射存储的多少个数据
};
}