bitset的一个简单实现
最近有一个上亿的数据(数据较平均,重复量较小)进行排重的需求,综合考虑了各种方案,最后想到了一个简单的方案:
假设有1亿条数据需要排重,每条数据的关键字有40个字节,考虑使用hash_map,但是放入内存的话需要的内存最少为
100000000 * 40 / 1024 / 1024 / 1024 = 3.7252902984619140625 G
这是不能被接受的,因此准备采用bit_map算法,但是bit_map有可能被误删除,因此还是要保存一份数据的备份,考虑使用外存存储,虽然会牺牲一定的效率,但是可以被接受。
首先先封装了一下一个bitset的基本实现,以备后续bitmap算法操作bit位。
具体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/type.h>
class bitset {
public:
/**
* @brief 构造函数, 初始化bit数组
* @param size bit数组的大小
*
* @return
* void
*/
bitset(unsigned int size):set_size(size) {
set_data = (unsigned char *)malloc(set_size);
memset(set_data, 0, set_size);
}
/**
* @brief 析构函数
* @param 无
*
* @return
* 无
*/
~bitset() {
if (set_data != NULL) {
free(set_data);
set_size = 0;
}
}
public:
/**
* @brief 将指定位置置位为 1
* @param pos bit位位置
*
* @return
* void
*/
void set(unsigned int pos) {
unsigned char block = set_data[pos / 8];
int index = pos % 8;
set_data[pos / 8] |= (0x1 << index);
}
/**
* @brief 将指定位置重置为 0
* @param pos bit位位置
*
* @return
* void
*/
void reset(unsigned int pos){
unsigned char block = set_data[pos / 8];
int index = pos % 8;
set_data[pos / 8] &= (( ~0 ) ^ 1 << index);
}
/**
* @brief 取指定位置的bit位的值
* @param pos bit位位置
*
* @return
* 返回 pos 位置的bit位的值,0 / 1
*/
unsigned int get(unsigned int pos) {
unsigned char block = set_data[pos / 8];
int index = pos % 8;
return (block & (0x1 << index)) > 0 ? 1 : 0;
}
private:
unsigned int set_size; // bitset的大小
unsigned char * set_data; // bitset存储的内存首地址
};
代码超级简单,只实现了三个方法:
置位方法, 该方法把指定位置的bit位置位1
设 A 取值为 0 或1
则有
0 | A = A
1 | A = 1
因此我们只需要将我们需要重置的位设置为1,其他位置位0即可
例如:
将 数字AAAAAAAA的第5位置位为1
只需要 AAAAAAAA | 00001000即可获得结果AAAA1AAA/** * @brief 将指定位置置位为 1 * @param pos bit位位置 * * @return * void */ void set(unsigned int pos) { unsigned char block = set_data[pos / 8]; int index = pos % 8; set_data[pos / 8] |= (0x1 << index); }
- 重置方法 该方法把指定bit位重置为0,原理为:
设 A 取值为 0 或1
则有
0 & A = 0
1 & A = A
因此我们只需要将我们需要重置的位设置为0,其他位置位1即可
例如:
将 数字AAAAAAAA的第5位置位为0
只需要 AAAAAAAA & 11110111即可获得结果AAAA0AAA
/**
* @brief 将指定位置重置为 0
* @param pos bit位位置
*
* @return
* void
*/
void reset(unsigned int pos){
unsigned char block = set_data[pos / 8];
int index = pos % 8;
set_data[pos / 8] &= (( ~0 ) ^ 1 << index);
- 取bit位的值的方法
原理为:
设 A 取值为 0 或1
则有
0 & A = 0
1 & A = A
因此我们只需要将我们需要取的bit位设置为1,其他位置位0即可
例如:
将 数字AAAAAAAA的第5位置位为1
只需要 AAAAAAAA & 00001000即可获得结果0000A0000
若 A 为 0 则结果为0, 否则大于0
/**
* @brief 取指定位置的bit位的值
* @param pos bit位位置
*
* @return
* 返回 pos 位置的bit位的值,0 / 1
*/
unsigned int get(unsigned int pos) {
unsigned char block = set_data[pos / 8];
int index = pos % 8;
return (block & (0x1 << index)) > 0 ? 1 : 0;
}