大数据排序方案---外排序介绍

原文:http://blog.sina.com.cn/s/blog_62186b4601019uz1.html

我们一般提到排序都是指内排序,比如快排,堆排序,归并排序等,所谓内排序就是能把所有待排序的数据外进内存之中,比如,一个数组之中。但是如果文件太大,文件中的所有数据不能一次性的放入内存之中,快排,堆排序,归并排序等内排序就无法工作了。

    比如下面的程序生成了一个包含266万个int整型的文件,为了排序这266万个int整型,我们用外排序。

外排序

该算法分两个阶段:

阶段一:把原始数据分成M段,每次读取一段,存入一个数组,使用内排序算法对这一段数据进行排序,然后将排完序的数据写入一个临时文件。假定最大数组规模为10万个int型值,则每个临时文件中保存着10万个有序的int型值。我们用S1、S2、.....Sk表示这些临时文件,其中最后的一个数据段Sk,包含的数据个数可能不足10万。

 

阶段二:将每对有序数据段(比如S1跟S2、S3跟S4....)合并为一个大的有序的数据段,将其存入一个新的临时文件。重复此过程,直至只剩下一个数据段。

 

 

实现阶段一:

    在函数initializeSegments中,我们将largedata.dat中每个规模为MAX_ARRAY_SIZE(10万)的数据段依次放入数组并排序,使用快排,并将所有排完序的数据依次存入一个名为f1.dat的新文件中。函数返回数据段的数目。

阶段一代码如下:

外排序

实现阶段二:

    每个合并步骤中,两个有序数据段合并为一个新的更大的有序数据段,规模加倍,因此,数据段的数目减半。合并后数据无法放入内存中。合并步骤的实现方法是:首先将文件f1.dat中的前一半数据段移动到临时文件f2.dat中。然后将文件f1.dat的第一个数据段与文件f2.dat的第一个数据段合并,写入临时文件f3.dat中。(注 f1.dat中的数据段可能比f2.dat中的多一段,如果这样的话,在合并操作后,将其最后一段数据段直接复制到f3.dat中)

下面是合并所有数据段的代码:

外排序

 

完整的实现代码详见:http://www.oschina.net/code/snippet_176897_13955

(1)int numberOfSegments =initializeSegments(MAX_ARRAY_SIZE, "largedata.dat", "f1.dat");

从原文件中创建初始数据段,并将有序数据段存入文件f1.dat中。

(2)merge(numberOfSegments, MAX_ARRAY_SIZE, "f1.dat", "f2.dat", "f3.dat");

将f1中的文件合并到f3中,利用f2做辅助。函数merge递归的调用多次,完成多个合并操作。每个步骤将numberOfSegments减少一半,而将每个数据段的大小增至一倍。完成一个合并操作后,下一个合并步骤中将f3中的新数据段合并至f2中,用f1做辅助。因此新调用的合并函数应该为:

merge((numberOfSegments + 1) / 2, segmentSize * 2, f3, f1, f2);

递归函数merge当numberOfSegments变为1时终止,在此情况下,f1包含排好序的数据。将f1复制到sortedlargedata.dat。

 

外排序分析:

    在外排中,主要的代价是文件IO。假定原文件中待排序的数据个数为n。

    在阶段一种,从原文件读取了n个元素,并写入临时文件,因此阶段一的IO开销为O(n)。

    在阶段二中,在第一个合并操作之前,有序数据段的数目为n/c,其中c=MAX_ARRAY_SIZE。每个合并操作之后,有序数据段的数目减少一半。因此log(n/c)个步骤之后,数据段的数目为1。每个合并步骤中,从文件f1读取一半数据段,写入临时文件f2.f1剩余数据段与f2数据段进行合并。每个合并步骤的IO操作次数为O(n)。所以log(n/c)个合并操作总的IO次数为O(n)*log(n/c)。

    所以外排序的复杂度为O(nlogn)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值