Alex_McAvoy

想要成为渔夫的猎手

置换选择排序与最佳归并树

【引入】

外部排序 中讨论过,增大归并路数 $k$减少初始归并段个数 $r$,都可以减少归并趟数 $S$,进而减少 I/O 次数,以提高外部排序速度

若总的记录个数为 $n$,每个归并段长度为 $l$,则归并段个数 $\left \lceil \frac{n}{l} \rceil \right.$,采用内部排序得到的各个初始归并段,除最后一个外,长度都相同,其依赖于内部排序时可用内存工作区的大小

因此,为产生更长的初始归并段,以减少初始归并段数 $r$,引入了置换-选择算法

【置换选择排序】

设待排序文件为 F1,初始归并段输出文件为 FO,内存工作区为 WAFOWA 的初始状态为空,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 为空,由此得到全部初始归并段

需要注意的是,在工作区 WA 中选择 miniMax 记录的过程,需要用败者树来实现


以待排文件 FI 中的数据 $\{17,21,5,44,10,12,56,32,29\}$ 为例,设工作区 WA 容量为 $3$,排序过程如下:

输出文件 FO​ 工作区 WA miniMax 记录 输入文件 FI
$-$ $-$ $-$ $17,21,5,44,10,12,56,32,29$
$-$ $17,21,5$ $5$ $44,10,12,56,32,29$
$5$ $17,21,44$ $17$ $10,12,56,32,29$
$5,17$ $10,21,44$ $21$ $12,56,32,29$
$5,17,21$ $10,12,44$ $44$ $56,32,29$
$5,17,21,44$ $10,12,56$ $56$ $32,29$
$5,17,21,44,56$ $10,12,32$ $-$ $29$
$5,17,21,44,56,EOF$

此时,在工作区 WA 中选不出新的 miniMax 记录,得到一个初始归并段 $\{5,17,21,44,56\}$,工作区 WA 非空,重新选择 miniMax 记录,以继续获得初始归并段

输出文件 FO 工作区 WA miniMax 记录 输入文件 FI
$-$ $10,12,32$ $10$ $29$
$10$ $29,12,32$ $12$ $-$
$10,12$ $29,32$ $29$ $-$
$10,12,29$ $32$ $32$ $-$
$10,12,29,32$ $-$ $-$ $-$
$10,12,29,32,EOF$ $-$ $-$ $-$

此时,得到另一个初始归并段 $\{10,12,29,32\}$,工作区 WA 为空,算法终止

得到全部的初始归并段 $\{5,17,21,44,56\}$、 $\{10,12,29,32\}$

【最佳归并树】

文件经过置换选择排序后,得到的是长度不等的初始归并段,为使 I/O 次数最小,那么就需要合理的组织长度不等的初始归并段的归并顺序

霍夫曼树的思想推广到 $k$ 叉树的情形,在归并树中,让记录数最少的初始归并段先归并,记录数多的初始归并段最晚归并,即可建立总 I/O 次数最少的最佳归并树

若初始归并段不足以形成一棵严格 $k$ 叉树,需要添加长度为 $0$ 的虚段

设度为 $0$ 的结点有 $n_0$ 个,度为 $k$ 的结点有 $n_k$ 个,则对于严格 $k$ 叉树有 $n_0=(k-1)n_k+1$,由此可得:

若 $(n_0-1)\%(k-1)=0$,则说明这 $n_0$ 个叶结点(初始归并段)正好可以构成 $k$ 叉归并树,此时内结点有 $n_k$ 个

若 $(n_0-1)\%(k-1)=u\neq 0$,则说明这 $n_0$ 个叶结点中有 $u$ 个多余,不能包含在 $k$ 叉树中,为构造包含所有 $n_0$个初始归并段的 $k$ 叉归并树,应在原有 $n_k$ 个内结点的基础上再增加 $1$ 个内结点,代替一个叶结点的位置,被代替的叶结点再加上多出的 $u$ 个叶结点($k-u-1 $个空归并段),即可建立归并树


如下图,用 $8$ 个归并段构造 $3$ 叉树,由于有:

说明了 $7$ 个归并段刚好构成一棵严格 $3$ 叉树,为此,将叶子 $5$ 变为一个内结点,再添加 $3-1-1=1$ 个空归并段,即可构成一棵严格 $k$ 叉树

感谢您对我的支持,让我继续努力分享有用的技术与知识点!