Chapter 09 外排序
9.0 引言¶
- 内存是一种有限的资源, 现实世界的数据是海量的, 需要外部存储器的支持
- 外存文件的排序本质上还是借助内排序完成, 需要多次内外村之间的数据交换
9.1 计算机存储器¶
9.2 文件的组织与管理¶
参见 ICS
9.3 外排序¶
- 根据内存大小, 将外存中的数据文件划分成若干段, 每次读入一段用内排序方法进行排序.
- 已排好序的段称为 顺串或归并段
- 顺串写回外存等待进一步处理, 让出内存空间处理文件的其它未排序段


9.3.1 置换选择排序¶
- 将文件生成若干初始顺串 (顺串越长越好, 个数越少越好)
- 借助 RAM 中的堆完成
流程:
- 初始化最小堆, 从缓冲区读 \(M\) 个记录到数组中, 设置堆尾标志 \(\text{LAST}=M-1\), 建立最小堆
- 重复以下步骤直至堆空:
(a) 将具有最小关键码值的记录送到输出缓冲区
(b) 设 \(R\) 是输入缓冲区下一条记录
(i) 若 \(R\) 的关键码不小于刚输出的关键码, 将 \(R\) 放到根节点.
(ii) 否则, 使用 \(\text{LAST}\) 位置替代根节点, 把 \(R\) 放到 \(\text{LAST}\) 位置并设置LAST=LAST-1
(c) 重新调整堆
算法结束后, RAM 填满了不能处理的数据, 直接建成堆留待下一顺串处理.
平均顺串长度:
\[
Avg(M)=\frac{1}{2}(Avg(M)+1)+\frac{1}{2}(Avg(M-1)+1)
\]
\[
Avg(M)=Avg(M-1)+2
\]
因此 \(Avg(M)=2M\)
9.3.2 归并排序¶
二路归并: 合并树高 \(\lceil \log_2m\rceil\)+1, 进行 \(\lceil \log_2m\rceil\) 遍扫描. 两个输入缓冲区, 一个输出缓冲区
通过减少顺串个数和增加同时归并的顺串数量可以减少归并趟数.
最佳归并树: K 叉 Huffman 树
总访外次数: Huffman 树叶节点带权路径和 \(\times 2\) (读+写)
在做 K 路归并的时候, 每次都要做 k-1 次比较, 代价较大, 因此诞生两种选择树: 赢者树和败者树
9.3.3 赢者树¶
用完全二叉树作为存储结构. 叶节点用数组 \(L[1..n]\) 表示, 内部节点用 \(B[1..n-1]\) 表示, \(B\) 实际存放的是 \(L\) 的索引.


9.3.3 败者树¶
败者树用父结点记录左右子结点进行比赛的败者, 而让胜者去参加更高阶段的比赛.
新增根节点 B[0] 存储整个比赛的胜者.


相比赢者树, 败者树更新的时候只需要和父节点比较即可. 相比胜者树比较次数不变但少了一次寻址 (不用访问兄弟节点)
