关于海量数据处理问题

面对3亿个手机号码,在仅有的1G内存限制下,如何实现每秒检索超过1000次的目标?本文探讨了使用位操作、哈希法、最大/最小堆和Bit-map等解决方案。特别是位操作策略,通过将号码映射到数组下标,用0或1表示存在与否,以节省空间并提高检索效率。
摘要由CSDN通过智能技术生成
问题: 假设一个文件中有9 亿条不重复的9 位整数,现在要求对这个文件进行排序。 
一般解题思路: 
1 、将数据导入到内存中 
2 、将数据进行排序 (比如插入排序、快速排序) 
3 、将排序好的数据存入文件 


难题: 
一个整数为4 个字节 

即使使用数组也需要900,000,000 * 4byte = 3.6G 内存

(详细过程如下:

1G=1024M=2^10=10^3

1M = 1024K=2^10=10^3

1K = 1024Byte = 2^10=10^3

1B = 8bit

 

对于32 位系统,访问2G 以上的内存非常困难,而且一般设备也没有这么多的物理内存 将数据完全导入到内存中的做法不现实 


其他解决办法: 
1 、导入数据库运算 
2 、分段排序运算 
3 、使用bit 位运算 


解决方案一: 数据库排序 
将文本文件导入到数据库,让数据库进行索引排序操作后提取数据到文件 

优点:操作简单 
缺点:运算速度慢,而且需要数据库设备。 


解决方案二: 分段排序 
操作方式: 
规定一个内存大小,比如200M ,200M 可以记录(200*1024*1024/4) = 52428800 条记录,我们可以每次提取5000 万条记录到文件进行排序,要装满9 位整数需要20 次,所以一共要进行20 次排序,需要对文件进行20 次读操作 

缺点: 
编码复杂,速度也慢( 至少20 次搜索) 


关键步骤: 
先将整个9 位整数进行分段,亿条数据进行分成20 段,每段5000 万条 
在文件中依次搜索0~5000 万,50000001~1 亿…… 
将排序的结果存入文件 


解决方案三:bit 位操作 
思考下面的问题: 
一个最大的9 位整数为999999999 这9 亿条数据是不重复的 ,可不可以把这些数据组成一个队列或数组,让它有0~999999999(10 亿个) 元素,数组下标表示数值,节点中用0 表示这个数没有,1 表示有这个数 ,判断0 或1 只用一个bit 存储就够了 

声明一个可以包含9 位整数的bit 数组(10 亿) ,一共需要10 亿/8=120M 内存 
把内存中的数据全部初始化为0, 读取文件中的数据,并将数据放入内存。比如读到一个数据为341245909 这个数据,那就先在内存中找到341245909 这个bit ,并将bit 值置为1 ,遍历整个bit 数组,将bit 为1 的数组下标存入文件 


关键代码 
检查某一个char 里面(first) 的第second 位中存储的数据是否为1 

bool CompareBit (unsigned char first, int second) 
{ 
const static int mark_buf[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; 
if (second > .8) 
return false; 

return (first & mark_buf[second]) == mark_buf[second]; 
} 


将某一个char(Desc) 中的第source 位置为 1 

bool WriteToBit (unsigned char *Desc, int source) 
{ 
const static int mark_buf[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; 

if (source >  .8) 
return false; 

Desc[0] |= mark_buf[source]; 

return true; 
} 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值