外部排序算法整理

来源:互联网 发布:知乎for mac 编辑:程序博客网 时间:2024/06/07 09:49

的。于是乎谷狗了一下,学习了学习维基百科上关于外排的介绍,感觉还不错,确实解决了心中的疑问。其中,外归并排序和置换选择排序都讲得很清楚,还提供了一些不错的链接,如Jim Gray的Sort Benchmark网站,故在博客中Mark一下,以表感谢!

原文地址:http://zh.wikipedia.org/zh/外排序


外排序(External sorting)是指能够处理极大量数据的排序算法。通常来说,外排序处理的数据不能一次装入内存,只能放在读写较慢的外存储器(通常是硬盘)上。外排序通常采用的是一种“排序-归并”的策略。在排序阶段,先读入能放在内存中的数据量,将其排序输出到一个临时文件,依此进行,将待排序数据组织为多个有序的临时文件。尔后在归并段阶将这些临时文件组合为一个大的有序文件,也即排序结果。

目录

   [隐藏] 
  • 1 外归并排序
    • 1.1 附加的步骤
    • 1.2 优化性能
  • 2 其他算法
  • 3 外部链接
  • 4 参考

[编辑]外归并排序

外排序的一个例子是外归并排序(External merge sort),它读入一些能放在内存内的数据量,在内存中排序后输出为一个顺串(即是内部数据有序的临时文件),处理完所有的数据后再进行归并。[1][2]比如,要对 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. 执行九路归并算法,将结果输出到输出缓冲区。一旦输出缓冲区满,将缓冲区中的数据写出至目标文件,清空缓冲区。直至所有数据归并完成。

为了增加每一个有序的临时文件的长度,可以采用置换选择排序(Replacement selection sorting)。它可以产生大于内存大小的顺串。具体方法是在内存中使用一个最小堆进行排序,设该最小堆的大小为 M。算法描述如下:

  1. 初始时将输入文件读入内存,建立最小堆。
  2. 将堆顶元素输出至输出缓冲区。然后读入下一个记录:
    1. 若该元素的关键码值不小于刚输出的关键码值,将其作为堆顶元素并调整堆,使之满足堆的性质;
    2. 否则将新元素放入堆底位置,将堆的大小减 1。
  3. 重复第 2 步,直至堆大小变为 0。
  4. 此时一个顺串已经产生。将堆中的所有元素建堆,开始生成下一个顺串。[3]

此方法能生成平均长度为 2M 的顺串,可以进一步减少访问外部存储器的次数,节约时间,提高算法效率。

[编辑]附加的步骤

上述例子的外排序有两个步骤:排序和归并。我们用一次多路归并就完成了所有临时文件的归并,而并非按内存中的二路归并那样,一次归并两个子串,耗费 \log_2 n 次归并。外排序中不适用上述方法的原因在于每次读写都需要对硬盘进行读写,而这时非常缓慢的。所以应该尽可能减小磁盘的读写次数。

不过,在上述方法中也存在权衡。当临时文件(顺串)的数量继续增大时,归并时每次可从顺串中读入的数据减少了。比如说,50 GB 的数据量,100 MB 的可用内存,这种情况下用一趟多路归并就显得不划算。读入很多的顺串花费的时间占据了排序时间的大部分。这时,我们可以用多次(比如两次)归并来解决这个问题。

这时排序算法变为下述这样:

  1. 第一步不变。
  2. 将小的顺串合并为大一些的顺串,适当减小顺串的数目。
  3. 将剩余的大一些的顺串归并为最终结果。

和内排序一样,高效的外排序所耗的时间依然是 O(n\log n)。若利用好现在计算机上 GB 的内存,可使时间复杂度中的对数项增长比较缓慢。

[编辑]优化性能

计算机科学家吉姆·格雷的 Sort Benchmark 网站用不同的硬件、软件环境测试了实现方法不同的多种外排序算法的效率。效率较高的算法具有以下的特征:

  • 并行计算
    • 用多个磁盘驱动器并行处理数据,可以加速顺序磁盘读写。[4]
    • 在计算机上使用多线程,可在多核心的计算机上得到优化。
    • 使用异步输入输出,可以同时排序和归并,同时读写。
    • 使用多台计算机用高速网络连接,分担计算任务。[5]
  • 提高硬件速度
    • 增大内存,减小磁盘读写次数,减小归并次数。
    • 使用快速的外存设备,比如 15000 RPM 的硬盘或固态硬盘。
    • 使用性能更优良个各种设备,比如使用多核心 CPU 和延迟时间更短的内存。
  • 提高软件速度
    • 对于某些特殊数据,在第一阶段的排序中使用基数排序。
    • 压缩输入输出文件和临时文件。

[编辑]其他算法

外归并排序法并不是唯一的外排序算法。另外还有外分配排序,其原理类似于内排序中的桶排序。在归并排序和桶排序之间存在数学上的某种对偶性。[6] 此外还有一些不耗费附加磁盘空间的原地排序算法。

[编辑]外部链接

  • STXXL, 一个包含外归并排序的代码包
  • 外归并排序示例
  • 多路归并实现
  • Java 语言外归并排序

[编辑]参考

  1. ^ Donald Knuth, The Art of Computer Programming, Volume 3: Sorting and Searching, Second Edition. Addison-Wesley, 1998, ISBN 0-201-89685-0, Section 5.4: External Sorting, pp.248–379.
  2. ^ Ellis Horowitz and Sartaj Sahni, Fundamentals of Data Structures, H. Freeman & Co., ISBN 0-7167-8042-9.
  3. ^ 张铭、王腾蛟、赵海燕. 数据结构与算法. 北京: 高等教育出版社. 2008:  pp.246-248. ISBN 978-7-04-023961-4.
  4. ^ Nikolas Askitis, OzSort 2.0: Sorting up to 252GB for a Penny
  5. ^ Rasmussen et al., TritonSort
  6. ^ J. S. Vitter, Algorithms and Data Structures for External Memory, Series on Foundations and Trends in Theoretical Computer Science, now Publishers, Hanover, MA, 2008, ISBN 978-1-60198-106-6.
0 0