位图数据结构

位图
将一个数据的每一位都来表示一个数,存在为1不存在为0,一个char有8位,或int的32位,通过运算关系可以将每一个无符号整数都映射到每一位上,从而实现大量数据的存储。

笔试题:给40亿个不重复的无符号整数,没脾气郭旭。给一个无符号数,如何快速判读一个数是否在这40亿个数中。

将这40亿个数全部置入位图相应的位上,有为1,没有为0,如果要找的数对应的位上为1,代表该数存在,否则不存在。

void BitMapInit(Bm* bm, size_t len)
{//初始化
    assert(bm);
    assert(len > 0);
    bm->bits=(char*)malloc(sizeof(char)*len>> 3);
    memset(bm->bits, 0, sizeof(char)*len >> 3);
    bm->len = len;
}
void BitMapDestory(Bm* bm)
{//销毁
    assert(bm);
    free(bm->bits);
    bm->len = 0;
    bm->bits = NULL;
}
void BitMapset(Bm* bm,int key)
{//加一个进位图
    assert(bm);
    int index=0;
    int tmp;
    index = key >> 3;//找到数据存放在第几个字节内
    tmp =key% 8;    //确定该值位于该字节的第几位
    bm->bits[index] |= 1 << tmp;
}
void BitMapreset(Bm* bm, int key)
{//将一个数清除
    assert(bm);
    int index = key >> 3;
    int tmp = key % 8;
    bm->bits[index] &= ~(1 << tmp);  //将1左移到该数的位置取反相与
}
void print(Bm* bm, size_t len)
{
    assert(bm);
    assert(len > 0);
    int i = 0;
    int j = 0;
    for (i = 0; i < bm->len>>3; i++)
    {
        for (j = 0; j < 8; j++)
        {
            printf("%d", (bm->bits[i] >> j) & 1);
            printf("\n");
        }
    }
}


int main()
{


    Bm bm;
    BitMapInit(&bm, 24)//最大位数可以输入-1
    BitMapset(&bm, 3);
    BitMapset(&bm, 14);
    BitMapset(&bm, 6);
    BitMapset(&bm, 18);
    BitMapset(&bm, 22);
    BitMapreset(&bm, 14);
    BitMapreset(&bm,22);
    print(&bm,24);
    BitMapDestory(&bm);
    return 0;
}

位图
优点:速度快,内存空间占用小,能表示大范围数据

缺点:
1.可读性差
2.存储元素的个数比一般元素要多,但是存储元素的大小受空间大小的限制。

位图的应用

1.给定100亿个整数,设计算法找到只出现一次的整数
100亿个数据中只出现依次的数据,依旧采用位图的结构,此时由于要判断出现的次数,我们采用两位来表示,00表示不存在,01表示存在依次,10表示存在两次以上。

2.给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集
此时内存明显不够用此时我们将两个文件100亿个数据分别分成1000份,每份文件使用位图存放,然后将两个文件的每一份相与,与完如果对应位上仍旧为一说明有交集

位图变形:

1.1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
我们需要将100亿个数据分成1000份文件,将每个文件的数据通过位图存储,我们采用两个比特位
00:没有出现,01,出现一次,10出现2次,11舍弃,再将这1000个文件中出现出现两次的数据进行输出

猜你喜欢

转载自blog.csdn.net/M_jianjianjiao/article/details/82668311