Kol*_*Kir 36 sorting algorithm mergesort external-sorting
我试图理解外部合并排序算法是如何工作的(我看到了相同问题的一些答案,但没有找到我需要的东西).我正在阅读Jeffrey McConnell撰写的"分析算法"一书,我正在尝试实现那里描述的算法.
例如,我有输入数据:3,5,1,2,4,6,9,8,7,我只能将4个数字加载到内存中.
我的第一步是读取4个数字块的输入文件,在内存中对它们进行排序,然后将一个写入文件A,然后写入文件B.
我有:
A:[1,2,3,5][7]
B:[4,6,8,9]
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,如果它们不适合内存,我如何将这些文件中的块合并到较大的文件中呢?杰弗里麦康奈尔写道,我需要阅读半块并将它们合并到下一个文件C和D.
但我得错了序列:
C:[1,2,4,6,3,8,5,9]
D:[7]
Run Code Online (Sandbox Code Playgroud)
有人可以提供分步说明的例子吗?
PS:我理解如何通过读取文件来合并数字,但是如何使用内存缓冲区来减少I/O操作呢?
Sav*_*vas 30
首先,通过对4个数字的部分数字进行排序,您应该获得3个数据块.
A:[1,2,3,5]
B:[4,6,8,9]
C:[7]
Run Code Online (Sandbox Code Playgroud)
然后你将读取每个文件的一半(忽略C,因为它不适合)并合并它们.所以,你将加载到内存{[1,2],[4,6]}.您将进行临时合并并将结果写入新的块D:
Compare 1 and 4 -> D:[1]
Compare 2 and 4 -> D:[1, 2]
Run Code Online (Sandbox Code Playgroud)
现在,在RAM中的A部分完成了合并,所以现在你必须把它的后半部分带到内存中.现在你的记忆将有{[3,5],[4,6]}.
Compare 3 and 4 -> D:[1, 2, 3]
Compare 5 and 4 -> D:[1, 2, 3, 4]
Compare 5 and 6 -> D:[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
所有的块A都合并了,所以现在只需将B的其余部分附加到D中
D:[1,2,3,4,5,6,8,9]
Run Code Online (Sandbox Code Playgroud)
现在你必须使用块C和D执行相同的过程.请记住,在另一个示例中,C可以有多个数字.通过mergind C和D,您将获得一个新的块E,它将成为最终的排序文件.
另请注意,在更大的示例中,您可能需要更多合并阶段.例如,如果您有20个数字要排序,您将创建5个4个数字的块,然后您将每次合并并合并其中两个,产生2个8个数字的块(加上4个数字的一个额外),以及然后将较新的块合并为16个数字中的一个,依此类推.
您将同时遍历文件.
从每个文件的开头开始,继续选择哪个文件的元素不大于另一个文件的元素(即小于或等于),将该元素输出到新文件并增加迭代器.
从你上次的陈述来看,目前还不清楚你是否已经知道这样做了,但这就是你需要做的全部,因为:
你只需要为每个文件在内存中有一个数字,当然还有任何索引和其他变量,这些变量可能在本练习中被忽略.
您只需要读取每个文件一次,因为您可以在此过程中将文件保持在正确的位置,这样您就不需要再次读取整个文件以找到正确的位置.
因此对于:
A:[1,2,3,5]
B:[4,6,8,9]
Run Code Online (Sandbox Code Playgroud)
你将从每个文件的第一个元素开始 - 1和4.
该1较小,所以你输出的新文件,并移动到2.
2小于4,所以你输出并继续前进3.
3小于4,所以你输出并继续前进5.
4小于5,所以你输出并继续前进6.
5小于6,所以你输出那个然后你已经到了A的末尾.
现在只输出B的其余部分:6, 8, 9.
这给了你[1,2,3,4,5,6,8,9].