数据结构—排序(Part Ⅳ)—外部排序


数据结构-排序(第十章)的整理笔记,若有错误,欢迎指正。

外部排序

  • 文件存储在外存上,因此外排序方法与各种外存设备的特征有关,外存设备大体上可以分为两类:一类是顺序存取设备,例如磁带,另一类是直接存取设备,例如磁盘。
  • 磁帯(tape)出现在20世纪50年代早期,是一种典型的顺序存取设备,它是通过读写头读写数据的。磁带对于检索和修改操作都很不方便,其主要用于处理很少需要修改的并且进行顺序存取的信息,特别用作备份数据的设备。
  • 磁盘是一种直接存取的外存设备,它不仅能够进行顺序存取,而且能直接存取任何记录,它的存取速度比磁带快得多。磁盘分为硬盘软盘两种,硬盘的容量比软盘大得多,而且存取速度也比软盘快得多。
  • 目前磁盘多使用带有可移动式的磁头,从中可以看到,整个磁盘由多个盘片组成,固定在同一轴上沿一个固定方向高速旋转,每个盘片包括上、下两个盘面,每个盘面用于存储信息,每个盘面有一个读写头,有读写头是固定在一起同时同步移动的。在一个盘面上读写头的轨迹称为磁道,磁道就是磁面上的圆环。各个磁面上半径相同的磁道总和称为个柱面。在一个磁道内又分为若干个扇面。一般情况下,把一次向磁盘写入或读出的数据称为一个物理块,一个物理块通常由若干个记录组成。
  • 对于磁盘而言,影响存取时间的因素有3个,即搜索时间(磁头定位到指定柱面所需要的时间)、等待时间(磁头定位到磁道的指定扇区所需要的时间)和传送时间(从磁盘或向磁盘传送一个物理块的数据所需要的时间)。
  • 外排序的基本方法是归并排序法,它分为以下两个步骤:
  1. 生成若干初始归并段(顺串):将一个文件(含待排序的数据)中的数据分段读入内存,在内存中对其进行内排序,并将经过排序的数据段(有序段)写到多个外存文件上。
  2. 多路归并:对这些初始归并段进行多遍归并,使得有序的归并段逐渐扩大,最后在外存上形成整个文件的单一归并段,也就完成了这个文件的外排序。
  • 从中可以看出,外排序的时间主要花费在内、外存数据的交换(对应存取时间)和内排序上。

磁盘排序

  • 对存放在磁盘中的文件进行排序属于典型的外排序,称为磁盘排序(disk sort)。由于磁盘是直接存取设备,读写一个数据块的时间与当前读写头所处的位置关系不大,所以可以通过读写数据块的次数来衡量存取时间。
  • 若共N个记录,内存工作区可以容纳L个记录,则初始归并段数量 r = ⌈ N L ⌉ r= ⌈\frac NL⌉ r=LN

多路平衡归并与败者树

  • k路平衡归并:
    ①最多只能有k个段归并为⼀个;
    ②每⼀趟归并中,若有n个归并段参与归并,则经过这⼀趟处理得到 ⌈ n k ⌉ ⌈\frac nk⌉ kn个新的归并段。
  • 重要结论:采用多路归并可以减少归并趟数,从而减少磁盘I/O(读写)次数。
  • 对r个初始归并段,做k路归并,则归并树可用k叉树表示。若树高为h,则归并趟数= h − 1 h-1 h1= ⌈ l o g k r ⌉ ⌈log_k^r⌉ logkr(k越大,r越小,归并趟数越少,读写磁盘次数越少)。
  • 多路归并带来的负面影响:
    ①k路归并时,需要开辟k个输入缓冲区,内存开销增加。
    ②每挑选⼀个关键字需要对比关键字(k-1)次,内部归并所需时间增加。
  • !注意:并不是k越大,归并的效率就越好。
  • 优化:①增加归并路数k,进行多路平衡归并——代价1∶需要增加相应的输入缓冲区;代价2∶每次从k个归并段中选一个最小元素需要(k-1)次关键字对比(可用“败者树”减少关键字对比次数)。
    ②减少初始归并段数量r(可用“置换-选择排序”进⼀步减少初始归并段数量)。

  • 利用败者树实现多路平衡归并的过程是先建立败者树,然后对k个输入有序段进行k路平衡归并。
  • 败者树(tree of loser)是一棵有k个叶子结点的完全二叉树(可将大根堆看成胜者树),其中叶子结点存储参与归并的记录,分支结点存放关键字对应的段号。所谓败者是两个记录比较时关键字较大者,胜者是两个记录比较时关键字较小者。
  • 建立败者树是采用类似于堆调整的方法实现的,初始时令所有的分支结点指向一个含最小关键字(MINKEY)的叶子结点,然后从各叶子结点出发调整分支结点为新的败者即可。
  • 对k个有序段进行k路平衡归并的方法如下:
  1. 取每个输入有序段的第一个记录作为败者树的叶子结点,建立初始败者树:两两叶子结点进行比较,在双亲结点中存放比较的败者(关键字较大者),而让胜者去参加更高层的比赛,如此在根结点之上胜出的“冠军”是关键字最小者。
  2. 将胜出的记录写至输出归并段,在对应的叶子结点处补充其输入有序段的下一个记录,若该有序段变空,则补充一个大关键字(比所有记录关键字都大,设为 k m a x k_{max} kmax的虚记录。
  3. 调整败者树,选择新的关键字最小的记录:从补充记录的叶子结点向上和双亲结点的关键字比较,败者留在该双亲结点,胜者继续向上,直到树的根结点,最后将胜者放在根结点的双亲结点中。
  4. 若胜出的记录关键字等于 k m a x k_{max} kmax,则归并结束;否则转(2)继续。

置换-选择排序(生成初始归并段)

  • 减少初始归并段个数r也可以减少归并趟数S,若总的记录个数为n,每个归并段的长度为l,则归并段的个数 r = ⌈ n l ⌉ r=⌈\frac nl⌉ r=ln。采用内部排序方法得到的各个初始归并段长度都相同(除最后一段外),它依赖于内部排序时可用内存工作区的大小。因此,必须探索新的方法,用来产生更长的初始归并段,这就是置换一选择算法。
  • 设初始待排文件为FI,初始归并段输出文件为FO,内存工作区为WA,FO和WA的初始状态为空,WA可容纳个记录。置换—选择算法的步骤如下:
  1. 从FI中输入w个记录到工作区WA。
  2. 从WA中选出其中关键字取最小值的记录,记为MINIMAX记录。
  3. 将MINMAX记录输出到FO中去。
  4. 若FI不空,则从输入下一个记录到WA中。
  5. 从WA中所有关键字比MINIMAX记录的关键字大的记录中选出最小关键字记录,作为新的MINIMAX记录
  6. 重复3)~5),直至在WA中选不出新的MINIMAX记录为止,由此得到一个初始归并段,输出一个归并段的结束标志到FO中去。
  7. 重复2)~6),直至WA为空。由此得到全部初始归并段。

最佳归并树

  • 上图中各叶结点表示一个初始归并段,上面的权值表示该归并段的长度,叶结点到根的路径长度表示其参加归并的趟数,各非叶结点代表归并成的新归并段,根结点表示最终生成的归并段。树的带权路径长度WPL为归并过程中的总读记录数,WPL=2×1+(5+1+6+2)×1=16。故磁盘I/O总次数=2xWPL=32次。
  • 显然,归并方案不同,所得归并树亦不同,树的带权路径长度(I/O次数)亦不同。为了优化归并树的WPL,可将第4章中哈夫曼树的思想推广到m叉树的情形,在归并树中,让记录数少的初始归并段最先归并,记录数多的初始归并段最晚归并,就可以建立总的I/O次数最少的最佳归并树。
  • 上述8个初始归并段可构造成一棵3路归并的最佳归并树,按此树进行归并,仅需对外存进行326次读/写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值