今天面试遇到的海量数据问题,大家讨论下

warcao 2012-03-20 11:46:10
10亿个整数在一个文件中,要求去重,并按照各个整数出现的次数进行排序。有2g内存,无限硬盘。
注意排序安装出现的次数排的,不是按照数大小

比如文件中是
2
2
1
3
4
3
2

那结果就是
2
3
1
4
...全文
359 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanran_hill 2012-03-21
  • 打赏
  • 举报
回复
内存有限,硬盘无限,应该是B树处理,生成叶子节点吧
qixing1115 2012-03-21
  • 打赏
  • 举报
回复
如果数的分步范围比较平均的话可以这样:
1-10000放在文件1中
10000-20000放在文件2中
…………
…………
要是真有最大整数的化,就不太可取了,文件太多
数分步不均也不可取,可能一个文件会很大,还是无法处理
muyi66 2012-03-20
  • 打赏
  • 举报
回复
呃,没注意到最后那个需求。

去重处理时记录各数出现次数,而后重新按频次进行归并排序。
muyi66 2012-03-20
  • 打赏
  • 举报
回复
先用归并排序生成排好顺序的临时文件,再对临时文件做去重处理生成结果文件。
muyi66 2012-03-20
  • 打赏
  • 举报
回复
又想了一个主意:自己设计归并算法时可以同时做计数,把在每次归并里发现的同等数都先给计数,重复数字在同一组中只出现一次。

保存时每条记录就是2个字段:数值、频次。

这样,归并中对硬盘的写入操作会减少,且当归并结束时就已经完成了去重处理和频次计数。只要再按频次进行一次归并排序就完事了。
muyi66 2012-03-20
  • 打赏
  • 举报
回复
用map存在随机读写硬盘的问题,感觉不会有用归并先排序快。毕竟归并排序是顺序读写的,硬盘的速度压力最低。
yrnaaa 2012-03-20
  • 打赏
  • 举报
回复
10亿 = 0.93 G
10亿 = 0X3B9ACA00
如果是32位以内的数,用map就可以,但是map分段存几个文件,应该可以。
如果是64位,map分段存文件也是可以的,可能效率低。没有优化。
要是有个范围就简单多了。
map[key]++;
flytomylife 2012-03-20
  • 打赏
  • 举报
回复
且觉得得把数据分成四份,每份都依次,使用map记录出现的次数,而后排序,并保存到文件中,如此就得到了四个文件,而后利用归并排序思想,一边从四个文件中读取数据,一边把排好序的放入到文件中。
flytomylife 2012-03-20
  • 打赏
  • 举报
回复
学习了 呵呵 感觉文件的方法不错 呵呵
bluewanderer 2012-03-20
  • 打赏
  • 举报
回复
还可以再优化一下,如果文件还大于2GB但是其中值的可能性已经小于512M种了,可以用bucket sort。
bluewanderer 2012-03-20
  • 打赏
  • 举报
回复
1. 整除N余0的一个文件,余1的一个文件,余2的一个文件... 余N-1的一个文件。
2a. 任何一个文件小于2GB了,塞内存里排序,算个数然后按个数排序
2b. 继续用1的逻辑分割文件
3. 如果所有数据都处理好了以后,把存着按个数排序的所有文件归并成一个文件
深圳大哥 2012-03-20
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 warcao 的回复:]

引用 9 楼 luciferisnotsatan 的回复:

引用 6 楼 luciferisnotsatan 的回复:

题里没时间上的要求
用map就行了,key为数字,value累计出现次数,空间分配到硬盘上。
按次数输出,就是把之前的map遍历一边,value当key,key当value放到另一个map里。

第二次用multimap

另一种方法,利用文件名的话,不……
[/Quote]
我怎么感觉只要3G啊
深圳大哥 2012-03-20
  • 打赏
  • 举报
回复
http://www.cnblogs.com/chenyuming507950417/archive/2011/12/31/2297990.html
恨天低 2012-03-20
  • 打赏
  • 举报
回复
使用stl:map
zhangzhengmin 2012-03-20
  • 打赏
  • 举报
回复
关注,等牛人具体回答~!
开发者说 2012-03-20
  • 打赏
  • 举报
回复
因为硬盘无限,思路应该放在空间换时间上。不要对数值排序,排序的是数值的数量。
warcao 2012-03-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 luciferisnotsatan 的回复:]

引用 6 楼 luciferisnotsatan 的回复:

题里没时间上的要求
用map就行了,key为数字,value累计出现次数,空间分配到硬盘上。
按次数输出,就是把之前的map遍历一边,value当key,key当value放到另一个map里。

第二次用multimap

另一种方法,利用文件名的话,不排序都行。第一次先统计每个int出现了多少次。然后,次数为文件名,……
[/Quote]
第一次先统计每个int出现了多少次。 这个不好弄吧,内存不够 要16g吧
warcao 2012-03-20
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 quitepig 的回复:]

数的范围很重要。有明确规定吗?
[/Quote]

没具体说 不过不会是大整数 uint64应该够用
luciferisnotsatan 2012-03-20
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 luciferisnotsatan 的回复:]

题里没时间上的要求
用map就行了,key为数字,value累计出现次数,空间分配到硬盘上。
按次数输出,就是把之前的map遍历一边,value当key,key当value放到另一个map里。
[/Quote]
第二次用multimap

另一种方法,利用文件名的话,不排序都行。第一次先统计每个int出现了多少次。然后,次数为文件名,里面放int。最后就是遍历文件名,取出里面的int。
Kaile 2012-03-20
  • 打赏
  • 举报
回复
读文件到一个map, key是int, value是出现次数,map本身就是去重
再用一个multimap, key是次数,value 是整数

2G内存如果不够,中间用一个数据库保存第一个map


加载更多回复(5)

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧