您的位置:首页 > 其它

海量数据处理之bitmap实现

2013-05-08 20:23 295 查看
bitMap位图经常用来处理海量数据的问题,如3亿微信号和7亿QQ查重问题,电话号码去重问题,都可以用位图法来处理。

位图法思想较简单,即申请一个由比特构成的table,可在相应的位置置0或1.从而快速达到快速查找,同时又不会特别浪费空间。网上关于位图法的详细解释比较多。本文主要给出一个位图法简单的实现。

typedef char byte8;
typedef byte8 * bitMap;

int initBitMap(byte8 * & bitMap) {
bitMap = (byte8 *)malloc(1 << 29); //bitMap size: 2^29 * sizeof(byte8) = 2^32;
memset(bitMap, 0, 1 << 29);
return 0;
}

int setBitTrue(byte8 * bitMap, unsigned int loc) {
unsigned int segLength = sizeof(byte8) * 8;
bitMap[loc / segLength] |= (1 << (segLength - 1 - loc % segLength));
return 0;
}

int isTrue(byte8 * bitMap, unsigned int loc) {
unsigned int segLength = sizeof(byte8) * 8;
int ret = bitMap[loc / segLength] & (1 << (segLength - 1 - loc % segLength));
return ret > 0 ? 1 : 0;
}

int destroyBitMap(byte8 * bitMap) {
if (bitMap != NULL) {
free(bitMap);
}
bitMap == NULL;
return 1;
}


需要注意的问题:

1.计算好需要位图的大小以及范围。上面2^32个比特,下标范围0-2^32-1。

2.决定基本的存储方式。上面采用占8个比特的char

3.别忘了释放空间

例子:给一个int整数序列(数亿级),求连续数字最多为多少。如:100, 4, 200, 1, 3, 2 那么连续的数字最长为4(1,2,3,4)。

int longestConsecutive(vector<int> &num) {
bitMap bm;
initBitMap(bm);
unsigned int i = 0;
for (i = 0; i < num.size(); i++) {
unsigned int loc = num[i] + ((unsigned int)1 << 31);
setBitTrue(bm, loc);
}

unsigned int max = 0;
unsigned int count = 0;
for (i = 0; i < 0xffffffff; i++) {
if (isTrue(bm, i)) {
count++;
max = count > max ? count : max;
} else {
count = 0;
}
}
if (isTrue(bm, i)) { //最后的0xffffffff
count++;
max = count > max ? count : max;
}

destroyBitMap(bm);
return max;
}

int main() {
int arr[] = {100, 4, 200, 1, 3, 2};
vector<int> num;
num.assign(arr, arr + sizeof(arr) / sizeof(int));
printf("%u\n", longestConsecutive(num));
return 0;
}


注意:

1.负数的处理,整理右移。int范围:-2^31~2^31-1,对所有的数加2^31,则范围变成:0~2^32-1。即正好是unsigned int的范围。适合了数组下标来表示。

2.2^32-1可以用0xffffffff来表示。

3.由于unsigned int类型的i无法递增到2^32所以for循环条件是‘<’而不是'<=',那么需在循环结束后在执行一次。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: