131 lines
3.3 KiB
C++
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; // 映射存储的多少个数据
|
|
};
|
|
} |