目录
什么是外部排序?
在实际存储中经常需要对大文件进行存储,因为文件记录多,所以无法将整个文件复制到内存中进行排序,因此需要将待排序的记录存储在外存上,排序时把数据一部分一部分调入到内存中进行排序,在这个过程中进行多次内存和外存之间的交换,这种算法称为外部排序。
文件通常是按照块存储在磁盘中,操作系统也是按照块对磁盘上的信息进行读/写操作,因此外部排序的主要时间代价是考虑访问磁盘的次数,即I/O次数
1.外部排序主要排序算法
外部排序通常使用归并算法包括两个阶段:①根据内存缓冲区的大小,将外存上的文件分成若干个长度为l的子文件,依次读入内存在进行内部排序算法进行排序并将排序后的子序列文件重新写入到外存,称这些有序的子文件为归并段或顺串,②对这些归并段进行逐归并,使归并段逐渐从小到大,直到文件有序为止。
外部排序的总时间=内部排序时间+外存信息读/写的时间+内部归并的时间
增大归并路数,可减少归并趟数,进而减少总磁盘I/O次数(如二路归并转为四路归并只要2趟)
对r个初始归并段,做k路平衡归并,树的高度-1=向上取整(logkr)=归并趟数S,只要增大归并路数k,或减少初始归并段个数r,都能减少归并趟数S,进而减少总磁盘I/O次数
2.多路平衡数和败者树
每趟归并n个元素需要做(n-1)(k-1)次比较,S趟归并总共需要的比较次数是
S(n-1)(k-1)=[log k r] (n-1) (k-1)=[log 2 r] (n-1) (k-1)/[log 2 k]式中,(k-1)/[log 2 k]随k的增长而增长,因此内部归并时间随k的增长而增长。这将抵消由于增大k而减小外存访问次数所得到的效益。
败者树
败者树是树形选择排序的一种变体,可视为一颗完全二叉树,有点类似动漫的擂台大赛胜者和胜者pk败者留在原地的位置
因为k路归并的败者树深度为[log 2 k],因此k个记录中选择最小关键字,最多需要[log 2 k]比较。所以总的比较次数为 S(n-1)【log 2 k】=[log k r] (n-1)【log 2 k】= (n-1) [log 2 r]
使用败者树,内部排序的比较次数与k无关,只要内存空间允许,增大归并路数k将有效地减少归并树的高度,从而减小I/O次数,提高外部排序的速度。
3.置换-选择排序(生产初始归并段)
若中的记录个数为n,每个归并段的长度为l,则归并段的个数r=[n/l],采用内部排序算法得到的各个初始归并段长度都相同,它依赖于内部排序时可用内存工作区的大小。
实现过程
假设初始待排序文件为FI,初始归并段文件为输出文件FO,内存工作区为WA,FO与WA的初始状态为空,并假设内存工作去WA的容量可容纳w个记录,则置换-选择排序的操作的过程为:
(1)、从FI输入w个记录到工作区WA。
(2)、从WA中选出其中关键字最小的记录,记为MINIMAX记录。
(3)、将MINIMAX记录输出到FO中去。
(4)、若FI不为空,则从FI输入下一个记录到WA中。
(5)、从WA中所有关键字比MINIMAX记录关键字大的记录中选出最小关键字记录,作为新的MINIMAX记录。
(6)、重复(3)~(5),直至WA中选不出新的MINIMAX记录为止,由此得到一个初始归并段,输出一个归并段的结束标记到FO中去。
(7)、重复(2)~(6),直至WA为空。由此得到全部归并段。
4.最佳归并树
最佳归并树就相当于一个哈夫曼树
归并树的带权路径长度WPL为归并过程的总记录数
若初始归并段不足以构成一颗严格的k叉树时候,需要添加长度为0的虚段,按照哈夫曼树的规则,权为0的也在因离树根最远
如何添加虚段的数目
树中只包含度为0的节点和度为k的节点 设度为k的节点有nk个,度为0的节点有n0个,节点总数为n个则
初始归并段数量 + 虚段数量 = n0 n = n0 + nk k nk = n - 1(减去的是根节点,因为根节点入度为0,其余节点入读均为1) nk = (n0 - 1)/(k - 1)
-
(n0- 1)%(k - 1) = 0 : 刚好构成严格k叉树,不需要添加虚段
-
(n0 - 1)%(k - 1) = u : 不构成严格的k叉树,需要添加k - 1 - u个虚段