[求问] 在内存限制下如何对数组排序

340 天前
 main1234

如给定无序数组 arr ,长度为 100w ,但是机器可用内存只有 5w 数组长度,如何排序并写入文件 我的思路是类似归并排序 1.每次取数组 2.5w 长度排序,写入文件 file1 2.循环步骤 1 ,此时会有排序好的文件为 file1 至 fileN 3.合并 file$i 和 file$(i+1),此时会有一个 5w 长度的排序数组

问题是第 3 步后,如果处理接下来的文件??因为内存只能容纳 5w 长度的数组,怎么将 10w 长度数组合并呢

1931 次点击
所在节点    程序员
17 条回复
julyclyde
340 天前
用交换类排序呗,对内存(几乎)没需求
liuhan907
340 天前
这不就是外部排序+多路归并排序么
Tanix2
340 天前
如果每次取 2.5w 长度形成一个有序的 chunk 的话,共有 100w/2.5w=40 个 chunk ,之后使用 40 路归并排序,40 个 chunk 里每个先取比如说 0.5k 个元素(减少 I/O ,最好能达到一个 page 的大小,但是这里应该达不到),每次选出其中最大的一个元素放到缓冲区(大小为一个 page )。如果某个 chunk 在内存里没有元素了,那么从磁盘里再取 0.5k 个;如果输出缓冲区满了,写到磁盘里。
以上是二阶段多路归并排序,如果第一阶段形成的 chunk 数过多(比如大于 2.5w 了),可以考虑更多阶段。
changnet
340 天前
交换类排序冒泡排序这种,只需要一个原始数组,在原始数组上交换排序,不需要额外的内存。但 op 这明显原始数组都加载不进来,所以是不行的。

你用文件来排序是对的,但你排序好的 file1 和 file2 合并后并不是按顺序的啊,比如 file1 中最大的那个比 file2 中的那个还大。

要先把 100w 数据读出来,按排序因子分成 20 段写入 20 个文件,比如文件 1 只写入大小为 1~50000 ,文件 2 只写入 50001~100000 ,然后分别对这些文件进行排序,再把文件拼起来就行。

当然如果无法预估排序因子的大小,拆分不会那么顺利。因为是无序的,没法预知该拆成多少个文件,那就先拆成 2 个,对大于 5W 的文件继续拆分,直到所有文件都小于 5w 再排序
Tanix2
340 天前
有数据库的话,也可以考虑存到数据库里,让数据库给你排
BBCCBB
340 天前
比如每 1000 个数字加载出来, 排序, 写到一个小文件里, 然后每次合并两个有序文件. 归并排序这种思想. 比较两个文件的队头数字, 小的写到新的文件里.

最后比如留下了 20 个 5w 数字的有序文件..

然后继续 merge.. 得到 10 个 10w 有序的.
...
以此类推.
...
得到 2 个 50w 数字的有序文件,

最后

得到了 1 个 100w 数字的有序文件.

每次只读文件的第一个数字, 需要的内存很低的.
iOCZS
340 天前
既然不能整体读取到内存,为何要合并呢?
直接每 5W 存一个文件得了,虽然说追加写入也是可以,但你又不能整体读取。。。。
zhuangzhuang1988
340 天前
直接 sqlite 就可以了
eote
340 天前
darling19961030
340 天前
1. 将 100w 数据以 5w 大小分 20 组写入文件
2. 将这 20 组数据分别读到内存中排序
3. 读取 20 组数据的最小值到内存,比较出最小值写入文件,再从最小值所在组读入一个新数据
4. 再比较出最小值写入文件,再从最小值所在组读入新值
5. 直到读完 20 组数据,那写入的文件也是 100w 排序后的数据了
verrickt
340 天前
外部排序+流式处理
nuk
340 天前
随机从数组中取出 5w 个元素,排序后塞回原来的位置。当随机足够多次,排序稳定后,再检查一遍,如果没排序完,就接着循环。
hefish
340 天前
大学课本 《数据结构》 里面有详细描述。
LindsayZhou
340 天前
桶排序,每个桶做成一个文件。
LGA1150
339 天前
mmap 然后原地排序,剩下的交给操作系统
liguangsheng
339 天前
归并的时候被归并的两个文件都是有序状态的,不需要全部读到内存里再合并,两个文件指针,每次至少读一个数字就可以归并了
NASK
339 天前
外部排序+归并排序,也许是这样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1009465

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX