查看“︁外排序”︁的源代码
←
外排序
跳转到导航
跳转到搜索
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
'''外排序'''(External sorting)是指能够处理极大量[[数据]]的[[排序算法]]。通常来说,外排序处理的数据不能一次装入[[内存]],只能放在读写较慢的[[外存储器]](通常是[[硬盘]])上。外排序通常采用的是一种“排序-[[归并]]”的策略。在排序阶段,先读入能放在内存中的数据量,将其排序输出到一个临时文件,依此进行,将待排序数据组织为多个有序的临时文件。而后在归并阶段将这些临时文件组合为一个大的有序文件,也即排序结果。 ==外归并排序== 外排序的一个例子是外[[归并排序]](External merge sort),它读入一些能放在内存内的数据量,在内存中排序后输出为一个顺串(即是内部数据有序的临时文件),处理完所有的数据后再进行归并。<ref>[[高德纳|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.</ref><ref>* [[Ellis Horowitz]] and [[Sartaj Sahni]], ''Fundamentals of Data Structures'', H. Freeman & Co., ISBN 0-7167-8042-9.</ref>比如,要对900 [[兆字节|MB]]的数据进行排序,但机器上只有100 MB的可用内存时,外归并排序按如下方法操作: # 读入100 MB的数据至内存中,用某种常规方式(如[[快速排序]]、[[堆排序]]、[[归并排序]]等方法)在内存中完成排序。 # 将排序完成的数据写入磁盘。 # 读入每个临时文件(顺串)的前10 MB( = 100 MB / (9块 + 1))的数据放入内存中的输入[[缓冲区]],最后的10 MB作为输出缓冲区。(实践中,将输入缓冲适当调小,而适当增大输出缓冲区能获得更好的效果。) # 执行九路[[归并]]算法,将结果输出到输出缓冲区。一旦输出缓冲区满,将缓冲区中的数据写出至目标文件,清空缓冲区。一旦9个输入缓冲区中的一个变空,就从这个缓冲区关联的文件,读入下一个10M数据,除非这个文件已读完。这是“外归并排序”能在主存外完成排序的关键步骤 -- 因为“归并算法”(merge algorithm)对每一个大块只是顺序地做一轮访问(进行归并),每个大块不用完全载入主存。 为了增加每一个有序的临时文件的长度,可以采用[[置换选择排序]](Replacement selection sorting)。它可以产生大于内存大小的顺串。具体方法是在内存中使用一个[[最小堆]]进行排序,设该最小堆的大小为<math>M</math>。算法描述如下: # 初始时将输入文件读入内存,建立最小堆。 # 将堆顶元素输出至输出缓冲区。然后读入下一个记录: ## 若该元素的关键码值不小于刚输出的关键码值,将其作为堆顶元素并调整堆,使之满足堆的性质; ## 否则将新元素放入堆底位置,将堆的大小减1。 # 重复第2步,直至堆大小变为0。 # 此时一个顺串已经产生。将堆中的所有元素建堆,开始生成下一个顺串。<ref>{{cite book | title=数据结构与算法 | url=https://archive.org/details/shujujiegouyusua0000unse_v9s5 | publisher=高等教育出版社 | author=张铭、王腾蛟、赵海燕 | year=2008 | location=北京 | pages=pp.246-248 | isbn=978-7-04-023961-4}}</ref> 此方法能生成平均长度为<math>2M</math>的顺串,可以进一步减少访问外部存储器的次数,节约时间,提高算法效率。 ===附加的步骤=== 上述例子的外排序有两个步骤:排序和归并。我们用一次多路归并就完成了所有临时文件的归并,而并非按内存中的二路归并那样,一次归并两个子串,耗费<math>\log_2 n</math>次归并。外排序中不适用上述方法的原因在于每次读写都需要对硬盘进行读写,而这是非常缓慢的。所以应该尽可能减小磁盘的读写次数。 不过,在上述方法中也存在权衡。当临时文件(顺串)的数量继续增大时,归并时每次可从顺串中读入的数据减少了。比如说,50 GB的数据量,100 MB的可用内存,这种情况下用一趟多路归并就显得不划算。读入很多的顺串花费的时间占据了排序时间的大部分。这时,我们可以用多次(比如两次)归并来解决这个问题。 这时排序算法变为下述这样: # 第一步不变。 # 将小的顺串合并为大一些的顺串,适当减小顺串的数目。 # 将剩余的大一些的顺串归并为最终结果。 和[[内排序]]一样,高效的外排序所耗的时间依然是<math>O(n\log n)</math>。若利用好现在计算机上GB的内存,可使时间复杂度中的对数项增长比较缓慢。 ===优化性能=== 计算机科学家[[吉姆·格雷]]的[http://sortbenchmark.org/ Sort Benchmark]{{Wayback|url=http://sortbenchmark.org/ |date=20120113194954 }}网站用不同的硬件、软件环境测试了实现方法不同的多种外排序算法的效率。效率较高的算法具有以下的特征: * '''并行计算''' ** 用多个磁盘驱动器并行处理数据,可以加速顺序磁盘读写。<ref>Nikolas Askitis, [http://sortbenchmark.org/ozsort-2010.pdf OzSort 2.0: Sorting up to 252GB for a Penny] {{Wayback|url=http://sortbenchmark.org/ozsort-2010.pdf |date=20120105095831 }}</ref> ** 在计算机上使用多[[线程]],可在多核心的计算机上得到优化。 ** 使用[[异步输入输出]],可以同时排序和归并,同时读写。 ** 使用多台计算机用高速网络连接,分担计算任务。<ref>Rasmussen et al., [http://sortbenchmark.org/tritonsort_2010_May_15.pdf TritonSort] {{Wayback|url=http://sortbenchmark.org/tritonsort_2010_May_15.pdf |date=20120128044323 }}</ref> * '''提高硬件速度''' ** 增大内存,减小磁盘读写次数,减小归并次数。 ** 使用快速的外存设备,比如15000 RPM的硬盘或[[固态硬盘]]。 ** 使用性能更优良个各种设备,比如使用多核心[[CPU]]和延迟时间更短的内存。 * '''提高软件速度''' ** 对于某些特殊数据,在第一阶段的排序中使用[[基数排序]]。 ** 压缩输入输出文件和临时文件。 ==其他算法== 外归并排序法并不是唯一的外排序算法。另外还有外分配排序,其原理类似于内排序中的[[桶排序]]。在归并排序和桶排序之间存在数学上的某种[[对偶]]性。<ref>[[J. S. Vitter]], ''[http://www.ittc.ku.edu/~jsv/Papers/Vit.IO_book.pdf Algorithms and Data Structures for External Memory] {{Wayback|url=http://www.ittc.ku.edu/~jsv/Papers/Vit.IO_book.pdf |date=20110104233254 }}'', Series on Foundations and Trends in Theoretical Computer Science, now Publishers, Hanover, MA, 2008, ISBN 978-1-60198-106-6.</ref>此外还有一些不耗费附加磁盘空间的原地排序算法。 ==外部链接== *[http://stxxl.sourceforge.net/ STXXL,一个包含外归并排序的代码包]{{Wayback|url=http://stxxl.sourceforge.net/ |date=20111124143605 }} *[http://cis.stvincent.edu/html/tutorials/swd/extsort/extsort.html 外归并排序示例]{{Wayback|url=http://cis.stvincent.edu/html/tutorials/swd/extsort/extsort.html |date=20151101074022 }} *[http://code.google.com/p/kway 多路归并实现]{{Wayback|url=http://code.google.com/p/kway |date=20151008155255 }} *[http://code.google.com/p/externalsortinginjava/ Java语言外归并排序]{{Wayback|url=http://code.google.com/p/externalsortinginjava/ |date=20141224063944 }} ==参考== <references/> [[Category:排序算法]]
该页面使用的模板:
Template:Cite book
(
查看源代码
)
Template:Wayback
(
查看源代码
)
返回
外排序
。
导航菜单
个人工具
登录
命名空间
页面
讨论
不转换
查看
阅读
查看源代码
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
工具
链入页面
相关更改
页面信息