数据结构——外部排序

数据结构——外部排序文章详细介绍了外部排序的基本思想 主要以归并排序为例 包括如何将大文件分块 内存中排序以及多路平衡归并以减少 I O 次数

大家好,欢迎来到IT知识分享网。

一、外部排序

1.1 基本思想

有时,待排序的文件很大,计算机内存不能容纳整个文件,这时候对文件就不能单纯的使用内部排序了,还得采取一些其他的策略。因此需要将待排序的记录存储到外存上,排序时再将数据一部分一部分地调用内存进行排序,在排序过程中需要多次进行内存和外存之间地交换,这种排序方法就成为外部排序。

文件通常是按块存储在磁盘上的,操作系统也是按块对磁盘上的信息进行读写的。因为磁盘读/写的机械动作所需的时间远远超过内存运算的时间,因此外部排序过程中的时间代价主要考虑访问磁盘的次数,即I/O次数。

外部排序常采用的排序方法是归并排序,这种归并方法由两个不同的阶段组成:

  1. 根据内存缓冲区大小,将外存中的文件分成若干个长度为 l l l的子文件,依次读入内存并利用内部排序方法对它们排序,并将排序后得到的有序子文件重新写回外存,称这些有序子文件为归并串或顺串
  2. 对这些归并段进行逐趟归并,使归并段(有序子文件)逐渐由小到大,直至得到整个有序文件为止。

1.2 图解

(2)将 ( 36 , 8 , 26 ) (36,8,26) (36,8,26) ( 42 , 9 , 48 ) (42,9,48) (42,9,48)分别存入输入缓冲区 1 1 1和输入缓冲区 2 2 2
在这里插入图片描述

(3)将输入缓冲区 1 1 1和输入缓冲区 2 2 2的数据进行递增排序
在这里插入图片描述
(4)将输入缓冲区 1 1 1和输入缓冲区 2 2 2的数据通过输出缓冲区逐一写入外存,形成一个有序归并段
在这里插入图片描述
(5)对于 ( 1 , 37 , 25 ) (1,37,25) (1,37,25) ( 45 , 27 , 28 ) (45,27,28) (45,27,28)进行上述同样的操作后得到的结果:
在这里插入图片描述




(6) 对剩余 12 12 12块内存依次进行上述操作,总共需要进行 16 16 16次读操作和 16 16 16次写操作,得到初始归并段。
在这里插入图片描述

(7)第一次归并:读入归并段 1 1 1和归并段 2 2 2中的第一块磁盘(相对最小),进行排序:
在这里插入图片描述

(8)依次找出这两个输入缓冲区中最小元素,并将其移动到输出缓冲区中,当输出缓冲区满,则写入外存 ( 1 , 8 , 9 ) (1,8,9) (1,8,9)
在这里插入图片描述

(9)继续找出这剩余元素中的最小元素,直到某一个缓冲区中空,则读入其所属归并段的后一个内存块的数据,并继续进行上述操作。直到两个缓冲区都空,且归并段 1 1 1和归并段 2 2 2中的元素全部读入内存,此时归并段 1 1 1和归并段 2 2 2就得到了一个有序的递增序列。

输入归并段 1 1 1的第二块内存
在这里插入图片描述
排序完成,归并段 1 1 1和归并段 2 2 2递增有序
在这里插入图片描述
(10)对剩余的六个归并段进行上述操作,八个归并段→四个归并段
在这里插入图片描述
(11)第二次归并:继续采用此方法依次取出归并段 1 1 1和归并段 2 2 2(归并段 1 1 1为八个归并段时的归并段 1 1 1和归并段 2 2 2,归并段 2 2 2为八个归并段时的归并段 3 3 3和归并段 4 4 4)的各个块进行排序操作:四个归并段→两个归并段。
在这里插入图片描述
(12)第三次归并:继续排序归并段 1 、 2 1、2 12,形成最后的有序递增序列
在这里插入图片描述








1.3 外部排序的开销

总时间开销 = 内部排序所需时间 + 内部归并所需时间 + 外部读写所需时间

1.4 优化:多路平衡归并

若改用 4 4 4路归并排序,则只需 2 2 2趟归并,外部排序时的总读/写次数便减至 32 × 2 + 32 = 96 32×2+ 32= 96 32×2+32=96。因此,增大归并路数,可减少归并趟数,进而减少总的磁盘 I / O I/O I/O次数。

一般地,对 r r r个初始归并段,做 k k k路平衡归并,归并树可用严格 k k k叉树(即只有度为 k k k与度为 0 0 0的结点的 k k k叉树)来表示。第一趟可将 r r r个初始归并段归并为 ⌈ r / k ⌉ ⌈r/k⌉ r/k个归并段,以后每趟归并将 m m m个归并段归并成 ⌈ m / k ⌉ ⌈m/k⌉ m/k个归并段,直至最后形成一个大的归并段为止。 树的高度 − 1 = ⌈ l o g k r ⌉ = 归并趟数 S 树的高度-1=⌈log_kr⌉=归并趟数S 树的高度1=logkr=归并趟数S。可见,只要增大归并路数 k k k,或减少初始归并段个数 r r r,都能减少归并趟数 S S S,进而减少读写磁盘的次数,达到提高外部排序速度的目的。

二、败者树

为了使内部归并不受 k k k的增大的影响,引入了败者树。败者树是属性选择排序的一种变体,可视为一棵完全二叉树。

  1. 将每个归并段的第一个元素作为叶子结点加入败者树中
    在这里插入图片描述
  2. 从左至右、从上往下的更新分支节点的信息:判断其左右子树的大小,除了根节点(最上面那个结点)记录冠军来自哪个归并段外,其余各分支节点记录的是失败者来自哪个归并段。
    在这里插入图片描述
  3. 取出最小的元素 1 1 1后,从其所属的归并段中取出下一个元素 6 6 6,依次与从叶子结点到根节点的各个结点所记录的败者信息进行对比。
    在这里插入图片描述
    引进败者树后,选出最小的关键字,仅需 l o g 2 k log_2k log2k次比较(向上取整)。

可见,使用败者树后,内部归并的比较次数与 k k k无关了。因此,只要内存空间允许,增大归并路数 k k k将有效地减少归并树的高度,从而减少 I O IO IO次数,提高外部排序的速度。

值得说明的是,归并路数k并不是越大越好。归并路数 k k k增大时,相应地需要增加输入缓冲区的个数。若可供使用的内存空间不变,势必要减少每个输入缓冲区的容量,使得内存、外存交换数据的次数增大。当 k k k值过大时,虽然归并趟数会减少,但读写外存的次数仍会增加。

三、置换选择排序

使用选择置换排序,可以让每个初始段的长度不再受限于内存工作区大小,设内存工作区最多容纳 w w w个数据:

  1. 将待排序文件 F I FI FI输入 w w w个数据到内存工作区 W A WA WA
  2. 选择 W A WA WA中关键字最小的数据,输出到 F O FO FO中,并且用 M I N MIN MIN记录该最小关键字
  3. F I FI FI不空,则从 F I FI FI中继续输入文件到 W A WA WA
  4. W A WA WA中选出比 M I N MIN MIN更大的关键字的数据,输出并更新此最小关键字作为新 M I N MIN MIN
  5. 重复2~4直到 W A WA WA中的每个关键字都> M I N MIN MIN为止,由此得到一个新的归并段
  6. 重复2~5,直到 W A WA WA空,得到全部初始归并段

四、最佳归并树

  1. 性质和构造完全相同于哈弗曼树
  2. 与哈弗曼树的区别:
    • k k k叉树,其中 k > 2 k > 2 k>2时:需要判断是否能满足构造完全 k k k叉树,若不满足,则需要添加长度为 0 0 0的“虚段”
      • ( 初始归并段数量 − 1 ) % ( k − 1 ) = 0 (初始归并段数量 – 1) \% (k – 1) = 0 (初始归并段数量1)%(k1)=0,则能构成完全 k k k叉树
      • ( 初始归并段数量 − 1 ) % ( k − 1 ) = u ≠ 0 (初始归并段数量 – 1) \% (k – 1)= u ≠ 0 (初始归并段数量1)%(k1)=u=0,则说明需要添加 ( k − 1 ) − u (k – 1)-u (k1)u个虚段才能构成完全二叉树

参考文章

数据结构——外部排序

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120984.html

(0)
上一篇 2025-10-26 11:20
下一篇 2025-10-26 11:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信