您的位置:首页 > 其它

2路bit-map的应用:test.txt中有42亿个无符号整数,从小到大打印其中只出现过一次的数 。限制: 可用内存为1.5GB.

2015-06-28 18:17 447 查看
        先看这样一个问题:test.txt中有42亿个无符号整数,从小到大打印其中只出现过一次的数 。限制: 可用内存为1.5GB.  

        前面, 我们已经深入讨论了bit-map, 在本文中, 我们来看看2路bit-map, 其实, 它无非是对bit-map的扩展, 用了两个数组而已罢了。 既然已经熟悉了bit-map, 那我就不多啰嗦了, 直接给出代码:

#include <iostream>
#include <fstream>
using namespace std;

#define BIT_INT 32   // 1个unsigned int可以标志32个坑
#define SHIFT 5
#define MASK 0x1f
#define N 4294967296 // 2的32次方

unsigned int *a = NULL;
unsigned int *b = NULL;

// 标志数组a还是b(其实,a、b本是指针)
enum
{
arrA,
arrB
};

// 必须用堆
void createArr()
{
a = new unsigned int[1 + N / BIT_INT];
b = new unsigned int[1 + N / BIT_INT];
}

void deleteArr()
{
delete []a;
a = NULL;

delete []b;
b = NULL;
}

// 将所有位都初始化为0状态
void setAllZero()
{
memset(a, 0, (1 + N / BIT_INT) * sizeof(unsigned int));
memset(b, 0, (1 + N / BIT_INT) * sizeof(unsigned int));
}

// 设置第i位为1
void setOne(unsigned int i, int flag)
{
if(arrA == flag)
{
a[i >> SHIFT] |= (1 << (i & MASK));
}
else
{
b[i >> SHIFT] |= (1 << (i & MASK));
}
}

// 设置第i位为1
void setZero(unsigned int i, int flag)
{
if(arrA == flag)
{
a[i >> SHIFT] &= ~(1 << (i & MASK));
}
else
{
b[i >> SHIFT] &= ~(1 << (i & MASK));
}
}

// 检查第i位的值
int getState(unsigned int i, int flag)
{
if(arrA == flag)
{
return (a[i >> SHIFT] & (1 << (i & MASK))) && 1;
}

return (b[i >> SHIFT] & (1 << (i & MASK))) && 1;
}

void setStateFromFile()
{
ifstream cin("test.txt");  // 我测试的时候, 文件中的数据为:7 7 9 2 5 2 0 0 1 4 3 2 8
unsigned int n;
while(cin >> n)
{
// 采用2路bitmap, 其中a数组表示高位, b数组表示低位
// ab组合, 00表示出现0次, 01表示出现1次, 10表示出现2次, 11表示出现次数大于2次

int aState = getState(n, arrA);
int bState = getState(n, arrB);

if(0 == aState && 0 == bState) // 当前记录为0次
{
setOne(n, arrB);
}
else if(0 == aState && 1 == bState) // 当前记录为1次
{
setOne(n, arrA);
setZero(n, arrB);
}
else if(1 == aState && 0 == bState) // 当前记录为2次
{
setOne(n, arrB);
}
else // 当前记录大于2次,不做处理
{
NULL;
}
}
}

void printSingleNum()
{
unsigned int i = 0;
unsigned int bits = (1 + N / BIT_INT) * sizeof(unsigned int);
for(i = 0; i < bits; i++)
{
if(0 == getState(i, arrA) && 1 == getState(i, arrB))
{
cout << i << " ";    // 结果:1, 3, 4, 5, 8, 9
}
}

cout << endl;
}

int main()
{
createArr();
setAllZero();
setStateFromFile();
printSingleNum();
deleteArr();

return 0;
}
      运行一下, 结果与预期相符。 我运行的时候, 电脑卡的厉害啊。大家在玩的时候, 可以把N的值尽量调小一点, 比如N为429.

      OK, 2路bit-map的介绍到此为止, 多路bit-map与此同理, 简单。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: