位图:
假设给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
- 遍历:将元素保存起来,遍历查找。
- 树:创建一颗二叉搜索树。
- 排序:排序之后用二分查找的方法。
这些方法随着集合中元素的增加,我们需要的存储空间就越来越大、不过我们可以通过一个函数将一个元素映射成一个位矩阵中的一个点,这样一来,我们只要看看这个点是不是1就知道集合里有没有它了。
一个整形可以表示的最大数是4294967296即2^32,所以最少需要2^32个bit来存放整形数,2^32bit=512M,即步浪费空间又可以很快的查找。
.h
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
typedef struct BitMap
{
int *Bit;
int capacity;//比特位的总个数
int size;//比特位为1的个数
}BitMap;
//初始化比特位
void InitBitMap(BitMap *bit,int total);
//置1
void SetBitMap(BitMap *bit, int which);
//为1的个数
int SizeBitMap(BitMap *bit);
//置0
void ResetBitMap(BitMap *bit, int which);
//判断比特位是否为1
int TestSetMap(BitMap *bit, int which);
/////////////////////////////////////////////////////////////////////////////////
//初始化比特位
void InitBitMap(BitMap *bit, int total)
{
//total为创建的比特位个数
assert(bit);
//比特位的容量
bit->capacity = total;
bit->Bit = (int *)malloc(((total / 32) + 1)*sizeof(int));
if (bit->Bit == NULL)
{
assert(0);
return;
}
//置0
memset(bit->Bit, 0, ((total / 32) + 1)*sizeof(int));
bit->size = 0;
}
//置1
void SetBitMap(BitMap *bit, int which)
{
int index = 0;
int pos = 0;
assert(bit);
//确定在哪个字节
index = which >> 5;
//确定位置
pos = which % 32;
//置1
bit->Bit[index] = bit->Bit[index] | (1 << pos);
bit->size++;
}
//为1的个数
int SizeBitMap(BitMap *bit)
{
assert(bit);
return bit->size;
}
//判断比特位是否为1
int TestSetMap(BitMap *bit, int which)
{
assert(bit);
int index = 0;
int pos = 0;
assert(bit);
//确定在哪个字节
index = which >> 5;
//确定位置
pos = which % 32;
//该比特位为1返回1,否则返回0
bit->Bit[index] = bit->Bit[index] & (1 << pos);
return bit->Bit[index];
}
//置0
void ResetBitMap(BitMap *bit, int which)
{
int index = 0;
int pos = 0;
assert(bit);
//确定在哪个字节
index = which >> 5;
//确定位置
pos = which % 32;
//如果比特位是1,就置0 size--
if (TestSetMap(bit, which))
{
//置0
bit->Bit[index] = bit->Bit[index] & (~(1 << pos));
bit->size--;
}
}
测试:
#include"BitMap.h"
void Test()
{
BitMap bit;
//初始化比特位
InitBitMap(&bit,100);
//置1
SetBitMap(&bit, 9);
SetBitMap(&bit, 32);
SetBitMap(&bit, 22);
SetBitMap(&bit, 89);
SetBitMap(&bit, 78);
SetBitMap(&bit, 99);
if (TestSetMap(&bit, 32))
{
printf("32 bit is 1\n");
}
else
{
printf("32 bit is 0\n");
}
//置0
ResetBitMap(&bit, 32);
ResetBitMap(&bit, 22);
ResetBitMap(&bit, 12);
printf("Size=%d\n", SizeBitMap(&bit));
if (TestSetMap(&bit,32))
{
printf("32 bit is 1\n");
}
else
{
printf("32 bit is 0\n");
}
}
int main()
{
Test();
system("pause");
return 0;
}