Files
Learn-Algorithms/91 Algorithms In Big Data/外排序.md
T

32 lines
2.5 KiB
Markdown
Raw Normal View History

2017-03-21 11:46:19 +08:00
## 外排序
对磁盘文件的排序。将待处理的数据不能一次装入内存,先读入部分数据排序后输出到临时文件,采用「排序-归并」的策略。在归并阶段将这些临时文件组合为一个大的有序文件,也即排序结果。
`多路归并`,`最小堆`
比如,要对900 MB的数据进行排序,但机器上只有100 MB的可用内存时,外归并排序按如下方法操作:
1. 读入100 MB的数据至内存中,用某种常规方式(如快速排序、堆排序、归并排序等方法)在内存中完成排序。
2. 将排序完成的数据写入磁盘。
3. 重复步骤1和2直到所有的数据都存入了不同的100 MB的块(临时文件)中。在这个例子中,有900 MB数据,单个临时文件大小为100 MB,所以会产生9个临时文件。
4. 读入每个临时文件(顺串)的前10 MB( = 100 MB / (9块 + 1))的数据放入内存中的输入缓冲区,最后的10 MB作为输出缓冲区。(实践中,将输入缓冲适当调小,而适当增大输出缓冲区能获得更好的效果。)
5. 执行`九路归并`算法,将结果输出到输出缓冲区。一旦输出缓冲区满,将缓冲区中的数据写出至目标文件,清空缓冲区。一旦9个输入缓冲区中的一个变空,就从这个缓冲区关联的文件,读入下一个10M数据,除非这个文件已读完。这是“外归并排序”能在主存外完成排序的关键步骤 -- 因为“归并算法”(merge algorithm)对每一个大块只是顺序地做一轮访问(进行归并),每个大块不用完全载入主存。
为了增加每一个有序的临时文件的长度,可以采用`置换选择排序`(Replacement selection sorting)。它可以产生大于内存大小的顺串。具体方法是在内存中使用一个`最小堆`进行排序,设该最小堆的大小为M。算法描述如下:
1. 初始时将输入文件读入内存,建立最小堆。
2. 将堆顶元素输出至输出缓冲区。然后读入下一个记录:
* 若该元素的关键码值不小于刚输出的关键码值,将其作为堆顶元素并调整堆,使之满足堆的性质;
* 否则将新元素放入堆底位置,将堆的大小减1。
3. 重复第2步,直至堆大小变为0。
4. 此时一个顺串已经产生。将堆中的所有元素建堆,开始生成下一个顺串。[3]
此方法能生成平均长度为2M的顺串,可以进一步减少访问外部存储器的次数,节约时间,提高算法效率。