海量数据处理之bitmap实现

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 &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 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循环条件是‘<’而不是'<=',那么需在循环结束后在执行一次。


你可能感兴趣的:(Algorithms)