位图:也就是哈希表的变形,只是用一个bit位来存放一个数据。(准确来说是表示一个数据在该位置上存在不存在)
对于一个bit位,只可以存放0和1两种状态,所以位图只能解决的问题就是判断一个数据存在或者不存在。
代码实现:
//数据结构
typedef struct bitset
{
char* _bits;
int _size;
}bitset;
//各种函数的实现
//n代表的位的个数
void BitSetInit(bitset* phs, size_t n)
{
assert(phs && n >= 0);
//求出需要多少字节
int bit = (n >> 3) + 1;
phs->_bits = (char*)malloc(bit);
if (phs->_bits == NULL)
{
perror("use malloc!\n");
}
memset(phs->_bits, 0, bit);
phs->_size = n;
}
void BitSetDestory(bitset* phs)
{
assert(phs);
free(phs->_bits);
phs->_bits = NULL;
phs->_size = 0;
}
void BitSetSet(bitset* phs, size_t n)
{
assert(phs && n >= 0);
//先找到在那一个字节的位置
int bit = n >> 3;
int index = n % 8;
phs->_bits[bit] |= (1 << index);
}
void BitSetReSet(bitset* phs, size_t n)
{
assert(phs && n >= 0);
int bit = n >> 3;
int index = n % 8;
phs->_bits[bit] ^= ~(1 << index);
}
//存在 1
//不存在 0
int BitSetCheck(bitset* phs, size_t n)
{
assert(phs && n >= 0);
int bit = n >> 3;
int index = n % 8;
return (phs->_bits[bit] & (1 << index)) == 0 ? 0 : 1;
}
可以采用位图做的题:
1.给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何判断一个数是否在40个亿个数中。
解:对于一般的算法的话,对于一堆数要判断一个数是否在这一堆数里面,一般都是先将这一堆数存放到内存中去,然后再去遍历对比看是否存在。(对于较少的数可以使用,即占用内存较小)
但是对于这个这个题,40亿个数,若是整数的话,即有160亿个字节,也就是16G,如果要放到内存中去查找的话,这明显优点效率太慢,不显示。所以就可以采用位图来解决这个问题。使用位图的话,就可以大幅度的节省空间,只是用2G的内存,这和16G进行对比,节省了许多的内存空间。
因为要判断一个数在不在话,那就是只有两种状态,存在或者不存在。刚好就相当于一个bit位可以用1或者0,来分别表示存在或者不存在。
所以就可以采用位图来解决这个问题。
采用位图的话也就是相当于哈希表一样。可以使用这个数来作为多少位。从而可以对该位进行设定。
2.给定100亿个整数,设计算法找到只出现一次的数
3.给定两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集
4.1个文件有100亿个int,1G内存,设计算法直到出现次数不超过两次的所有整数。