引入bit-map主要是为了节约内存,举个很简单的例子:服务器端要记录一些用户的ID,其实某些时候只是查询这个ID有没有被使用,或者分配一个没有使用的ID给用户,如果允许用户的量是1KW,使用数组的方式是建立一个数组,然后把每一个用户ID保存在数组中,按照用户量的要求,那么数组的类型是unsigned int 足足使用了4个字节,那么使用的空间是1KW * 4 = 4KW bytes。或者也可以用unsigned char 类型使用数组下标表示ID,元素的值取两个不同的值表示两种状态,那么量就是1KW bytes。有些时候为了分配和回收的方便,会再分配同样大小的数组,一个为空闲数组,一个为忙数组,这个时候存储容量会翻倍。显然这两种方法都消耗了大量的内存,既然数组的下标能表示ID,那为什么bit位的位置不能呢?
#include <stdio.h>
#include <string.h>
typedef struct BitMap
{
unsigned long long *buffer;
unsigned int size;
unsigned int len;
unsigned int free;
unsigned int used;
unsigned int curSort;
}BitMap;
int FindNextZeroBit(BitMap *map)
{
int location = 0;
int index = 0;
int len = 0;
int i = 0;
int j = 0;
int realsort = 0;
unsigned char *p = NULL;
unsigned char temp = 0;
if(NULL == map)
{
printf("%s the map is NULL\n",__FUNCTION__ );
return -1;
}
if(NULL == map->buffer)
{
printf("%s %d the bitmap‘s buffer is NULL\n", __FUNCTION__, __LINE__);
return -1;
}
if(0 == map->free)
{
printf("%s %d there no zero bit\n", __FUNCTION__, __LINE__);
}
index = map->curSort;
index >>= 3;
len = map->len;
len <<= 3;
for(i=index; i<len+index; j=0)
{
realsort = i%len;
p = (unsigned char *)(map->buffer + (realsort>>3));
if(*((unsigned long long*)p) == 0xffffffffffffffff)
{
i -= i%8;
i += 8;
continue;
}
p += (realsort%8);
if(0xff != *p)
{
while( j < 8 )
{
temp = (*p) & (1 << j);
if(0 == temp)
{
location = (realsort<<3) + j;
map->curSort = location;
return location;
}
++j;
}
}
++i;
}
return -1;
}
int InitOneBitMap(BitMap* map, unsigned int size)
{
if(NULL == map)
{
return -1;
}
if(0 == size)
{
return -1;
}
map->len = size>>6;
map->buffer = (unsigned long long*)malloc((map->len)<<3);
if(NULL == map->buffer)
{
return -1;
}
memset(map->buffer, 0x00, (map->len)<<3);
map->size = size;
map->free = size;
map->used = 0;
map->curSort = 100;
return 1;
}
int SetOneBit(BitMap *map, unsigned int location)
{
if(NULL == map)
{
printf("%s the map is NULL\n", __FUNCTION__);
return -1;
}
if(location >= map->size)
{
printf("the location is bigger than size\n");
return -1;
}
*(map->buffer+(location>>6)) |= ((unsigned long long)1<<(location%64));
--map->free;
++map->used;
return 1;
}
int ClearOneBit(BitMap* map,unsigned int location)
{
if(NULL == map)
{
return -1;
}
if(location >= map->size)
{
return -1;
}
*(map->buffer+(location>>6)) &= ~((unsigned long long)1 << (location%64));
++map->free;
--map->used;
return 1;
}
int DestroyOneBitMap(BitMap* map)
{
if(NULL == map)
{
return -1;
}
if(NULL != map->buffer)
{
free(map->buffer);
}
free(map);
return 1;
}
int main(int argc, char *argv[])
{
int i = 0;
int pos = 0;
int size = 0;
BitMap *map = NULL;
map = (BitMap*)malloc(sizeof(BitMap));
if(NULL == map)
{
printf("alloc a map failed\n");
return 0;
}
printf("alloc a bitmap success\n");
printf("input the bit size: \n");
scanf("%d", &size);
InitOneBitMap(map, size);
/*
for(i=0; i< map->len; i++)
{
printf("buffer[%d] = %lx \n", i, map->buffer[i]);
}
*/
//using test
/*
for(i=0; i<4096; i++)
{
pos = FindNextZeroBit(map);
printf("pos : %d\n", pos);
if(-1 != pos)
{
SetOneBit(map, pos);
}
}
*/
for(i=0; i<map->len; i++)
{
printf("buffer[%d] = %llx \n", i, map->buffer[i]);
}
DestroyOneBitMap(map);
return 0;
}