//题目:在2.5亿个整数中找出不重复的整数,内存不足以容纳这2.5亿个整数。
#include<stdio.h>
#include<memory.h>
/*
每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义
用char数组存储2-Bitmap,不用考虑大小端内存的问题
映射关系如下:
|00 00 00 00| //映射|3 2 1 0|
|00 00 00 00| //映射|7 6 5 4|
……
|00 00 00 00|
*/
unsigned char flags[1000]; //数组大小自定义,存放各个整数出现的次数1000*4=4000个整数
unsigned get_val(int idx)
{
int i = idx/4; //确定数组位置
int j = idx%4; //确定8bit内位置
unsigned ret = (flags[i]&(0x3<<(2*j)))>>(2*j); //0x3十六进制表示00 00 00 11可控制某个整数,获取某个整数的出现次数
return ret;
}
/*
已经过位运算测试
*/
unsigned set_val(int idx, unsigned int val)
{
int i = idx/4;
int j = idx%4;
unsigned tmp = (flags[i]&~((0x3<<(2*j))&0xff)) | (((val%4)<<(2*j))&0xff); //或运算,前面保留其他位不变,后边重置所需修改的位
flags[i] = tmp;
return 0;
}
unsigned add_one(int idx)
{
if (get_val(idx)>=2) {
return 1;
}
else {
set_val(idx, get_val(idx)+1);
return 0;
}
}
//只测试非负数的情况;
//假如考虑负数的话,需增加一个2-Bitmap数组.
int a[]={1, 3, 5, 7, 9, 1, 3, 5, 7, 1, 3, 5,1, 3, 1,10,2,4,6,8,0};
int main()
{
int i;
memset(flags, 0, sizeof(flags));
printf("原数组为:");
for(i=0;i < sizeof(a)/sizeof(int); ++i) {
printf("%d ", a[i]);
add_one(a[i]);
}
printf("\r\n");
printf("只出现过一次的数:");
for(i=0;i < 100; ++i) {
if(get_val(i) == 1)
printf("%d ", i);
}
printf("\r\n");
return 0;
}
除了用2-Bitmap来计数标记以外,也可以用两个1-Bitmap来实现(如果考虑正负数的情况,就四个1-Bitmap)
转自:互联网