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

        先看这样一个问题: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与此同理, 简单。
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值