0.位图的概念
在哈希表中,如果要在表中存放一个整数,此时就要申请一个整型的空间来存放它,一个整型数据在32位或64位平台下都占4个字节。但是如果现在需要存储的数据是40亿个不重复的无符号整型,就需要160亿个字节来存储,1GB的内存是10亿个字节,那么160亿个字节需要16GB的内存来存放这些数据,而我们普通的电脑内存一般都是4G的内存,这显然是存放不下的。
这就引入了位图的概念:内存中的最小单位是比特。如果能用一个比特位来存放一个整型,只需要0.5GB(一个比特位可以表示一个整型,也就是4个字节,一个字节8个比特位那么总共需要5亿个字节的空间,既0.5G)的内存。但是一个比特位只可以表示0或1两种状态。如果要表示40亿个数据,可以申请0.5GB的内存。如果要存放的数据为10,映射到第10个比特位设置为1。如果要查找的数据为100,就查看第100个比特位处的状态,如果为1说明100存在于这堆数据中,如果是0说明不存在。这样用一个位来标识一个数据在或者不在的结构就是位图,实际上是哈希表的一种变形。
#####0.定义结构
//位图结构
typedef struct BitSet
{
char* _a;//也可以用其他的类型开辟数据
size_t _N;//位个数
}BitSet;
3.函数实现
#include "BitSet.h"
//初始化位图
void BitSetInit(BitSet* pbs, size_t n)
{
assert(pbs);
pbs->_N = n;
//这里一定要加1,假如n为33,33/8=4,但是要5个字节才能存的下
size_t size = n >> 3 + 1;
//开辟空间
pbs->_a = (char*)malloc(size);
//初始化为0
memset(pbs->_a, 0, size);
}
//销毁位图(释放malloc出来的空间)
void BitSetDestory(BitSet* pbs)
{
assert(pbs);
free(pbs->_a);
pbs->_a = NULL;
pbs->_N = 0;
}
//设置要存的值位置为1
void BitSetSet(BitSet* pbs, size_t x)
{
assert(pbs);
int index = x >> 3;//计算在第几个char里,相当于/8
int num = x % 8;//计算在第几位
pbs->_a[index] |= (1 << num);
}
//把已经设置为1的位置重新设置为0
void BitSetReSet(BitSet* pbs, size_t x)
{
assert(pbs);
int index = x >> 3;//相当于/8
int num = x % 8;
pbs->_a[index] &= ~(1 << num);
}
//判断所给数字是否存在(存在返回1,不存在返回0)
int BitSetTest(BitSet* pbs, size_t x)
{
assert(pbs);
int index = x >> 3;//相当于/8
int num = x % 8;
int ret = pbs->_a[index] & (1 << num);
if (0 == ret)
{
return 0;
}
else
return 1;
}
下边是测试代码:
#include"BitSet.h"
void TestBitSet()
{
BitSet bs;
BitSetInit(&bs, 20);
BitSetSet(&bs, 14);
BitSetSet(&bs, 2);
BitSetSet(&bs, 9);
BitSetSet(&bs, 19);
BitSetReSet(&bs, 19);
printf("%d\n", BitSetTest(&bs, 19));
printf("%d\n", BitSetTest(&bs, 3));
printf("%d\n", BitSetTest(&bs, 9));
printf("%d\n", BitSetTest(&bs, 4));
BitSetDestory(&bs);
}
int main()
{
TestBitSet();
return 0;
}